unit AVTypes;

interface

{$I ver.inc}

uses SysUtils, Classes, TypInfo, Rtti, Windows, Variants, AVRes,
     System.Generics.Defaults, System.Generics.Collections;

const
  AVTypeCount = 14;
  Bits: array [0 .. 7] of byte = (1, 2, 4, 8, 16, 32, 64, 128);
  NegBits: array [0 .. 7] of byte = (byte(not 1), byte(not 2), byte(not 4),
    byte(not 8), byte(not 16), byte(not 32), byte(not 64), byte(not 128));
  Numbers: TSysCharSet = ['0' .. '9'];
  DecimalSeparators: TSysCharSet = ['.', ','];
  HexCharsSet: TSysCharSet = ['0'..'9','A'..'F'];
  ByteHalfs: array[0..1] of byte = (15, 240);
  HexChars: array[0..15] of char = ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');

type
  TAVType = (avtString, avtByte, avtInt16, avtInt32, avtInt64, avtNativeInt,
    avtDouble, avtObject, avtDate, avtBool, avtValue, avtVariant, avtBitArray,
    avtRecord);

  PAVString = ^string;
  PAVByte = ^byte;
  PAVInt16 = ^Int16;
  PAVInt32 = ^Int32;
  PAVInt64 = ^Int64;
  PAVNativeInt = ^NativeInt;
  PAVDate = ^TDateTime;
  PAVBool = ^boolean;
  PAVValue = ^TValue;
  PAVVariant = ^Variant;
  PAVDouble = ^double;
  PAVObject = ^TObject;
  PAVBitArray = ^TBitArray;
  PAVRecord = Pointer;

  TBitArray = record
  private
    fData: TArray<byte>;
    function GetByteIndex(index: integer): integer;
    function GetBitIndex(index: integer): integer;
    function GetByteCount: integer;
    procedure SetByteCount(value: integer);
    procedure PrepareSize(ByteIndex: integer);
    function GetByte(index: integer): byte;
    procedure SetByte(index: integer; value: byte);
    function GetBit(index: integer): boolean;
    procedure SetBit(index: integer; value: boolean);
    function GetByteBit(ByteIndex, BitIndex: integer): boolean;
    procedure SetByteBit(ByteIndex, BitIndex: integer; value: boolean);
    function GetCount: integer;
    function GetAsString: string;
    procedure SetAsString(value: string);
  public
    procedure Clear;
    procedure GetData(var Buffer; BufferSize: integer);
    procedure SetData(var Buffer; BufferSize: integer);

    property Count: integer read GetCount;
    property Bit[index: integer]: boolean read GetBit write SetBit; default;
    property ByteBit[ByteIndex, BitIndex: integer]: boolean read GetByteBit write SetByteBit;
    property ByteCount: integer read GetByteCount write SetByteCount;
    property byte[index: integer]: byte read GetByte write SetByte;
    property Data: TArray<byte> read fData;
    property AsString: string read GetAsString write SetAsString;
  end;

  TAVRttiObj = record
    Instance: TObject;
    TypeInfo: PTypeInfo;
    fFields: TArray<TRttiField>;
    fFieldsInited: boolean;
    fProps: TArray<TRttiProperty>;
    fPropsInited: boolean;
    function GetFields: TArray<TRttiField>;
    function GetProperties: TArray<TRttiProperty>;
  private
    function GetItem(ForInstance: Pointer; ForTypeInfo: PTypeInfo; Path: string): TValue; overload;
    procedure SetItem(ForInstance: Pointer; ForTypeInfo: PTypeInfo; Path: string; value: TValue); overload;
    function GetItem(Path: string): TValue; overload;
    procedure SetItem(Path: string; value: TValue); overload;
  public
    class operator Explicit(obj: TObject): TAVRttiObj;

    function Invoke(Method: string; params: array of TValue): TValue;

    property Item[Path: string]: TValue read GetItem write SetItem; default;
    property Fields: TArray<TRttiField> read GetFields;
    property Properties: TArray<TRttiProperty> read GetProperties;
  end;

  function RttiContext: TRttiContext;

type

  TColorRec = packed record
    case Integer of
      0: (Color: LongInt);
      1: (
            Read: byte;
            Green: byte;
            Blue: byte;
            Alfa: byte;
         )
  end;

type

  TAVValue = class;

  TGetAsString = reference to function: string;
  TSetAsString = reference to procedure(value: string);
  TGetAsInteger = reference to function: integer;
  TSetAsInteger = reference to procedure(value: integer);
  TGetAsInt64 = reference to function: Int64;
  TSetAsInt64 = reference to procedure(value: Int64);
  TGetAsDate = reference to function: TDateTime;
  TSetAsDate = reference to procedure(value: TDateTime);
  TGetAsBool = reference to function: boolean;
  TSetAsBool = reference to procedure(value: boolean);
  TGetAsFloat = reference to function: double;
  TSetAsFloat = reference to procedure(value: double);
  TGetAsObject = reference to function: TObject;
  TSetAsObject = reference to procedure(value: TObject);
  TGetAsValue = reference to function: TValue;
  TSetAsValue = reference to procedure(value: TValue);
  TGetAsVariant = reference to function: Variant;
  TSetAsVariant = reference to procedure(value: Variant);
  TGetAsBitArray = reference to function: TBitArray;
  TSetAsBitArray = reference to procedure(value: TBitArray);
  TGetAsRtti = reference to function: TAVRttiObj;
  TGetFormatedValue = reference to function(format: string): string;
  TSetFormatedValue = reference to procedure(format: string; value: string);
  TCopyFrom = reference to procedure(value: TAVValue);
  TIsEmpty = reference to function: boolean;
  TCompareTo = reference to function(value: TAVValue): integer;

  TAVValueInfo = record
    ValueType: TAVType;
    ValueInfo: PTypeInfo;
    PValue: Pointer;


  end;

  TAVValue = class(TObject)
  private
    VInfo: TAVValueInfo;

    fGetAsString: TGetAsString;
    fSetAsString: TSetAsString;
    fGetAsInteger: TGetAsInteger;
    fSetAsInteger: TSetAsInteger;
    fGetAsInt64: TGetAsInt64;
    fSetAsInt64: TSetAsInt64;
    fGetAsDate: TGetAsDate;
    fSetAsDate: TSetAsDate;
    fGetAsBool: TGetAsBool;
    fSetAsBool: TSetAsBool;
    fGetAsFloat: TGetAsFloat;
    fSetAsFloat: TSetAsFloat;
    fGetAsObject: TGetAsObject;
    fSetAsObject: TSetAsObject;
    fGetAsValue: TGetAsValue;
    fSetAsValue: TSetAsValue;
    fGetAsVariant: TGetAsVariant;
    fSetAsVariant: TSetAsVariant;
    fGetAsBitArray: TGetAsBitArray;
    fSetAsBitArray: TSetAsBitArray;
    fGetFormatedValue: TGetFormatedValue;
    fSetFormatedValue: TSetFormatedValue;
    fCopyFrom: TCopyFrom;
    fIsEmpty: TIsEmpty;
    fCompareTo: TCompareTo;

    function GetValueType: TAVType;

    function GetAsString: string;
    procedure SetAsString(value: string);
    function GetAsInteger: integer;
    procedure SetAsInteger(value: integer);
    function GetAsInt64: Int64;
    procedure SetAsInt64(value: Int64);
    function GetAsDate: TDateTime;
    procedure SetAsDate(value: TDateTime);
    function GetAsBool: boolean;
    procedure SetAsBool(value: boolean);
    function GetAsFloat: double;
    procedure SetAsFloat(value: double);
    function GetAsObject: TObject;
    procedure SetAsObject(value: TObject);
    function GetAsValue: TValue;
    procedure SetAsValue(value: TValue);
    function GetAsVariant: Variant;
    procedure SetAsVariant(value: Variant);
    function GetAsBitArray: TBitArray;
    procedure SetAsBitArray(value: TBitArray);
    function GetAsRtti: TAVRttiObj;
    function GetFormatedValue(FormatStr: string): string;
    procedure SetFormatedValue(FormatStr: string; value: string);

    procedure InitMethods;

{$REGION 'Typed methods'}

//String
    function StringGetAsString: string;
    procedure StringSetAsString(value: string);
    function StringGetAsInteger: integer;
    procedure StringSetAsInteger(value: integer);
    function StringGetAsInt64: Int64;
    procedure StringSetAsInt64(value: Int64);
    function StringGetAsDate: TDateTime;
    procedure StringSetAsDate(value: TDateTime);
    function StringGetAsBool: boolean;
    procedure StringSetAsBool(value: boolean);
    function StringGetAsFloat: double;
    procedure StringSetAsFloat(value: double);
    function StringGetAsObject: TObject;
    procedure StringSetAsObject(value: TObject);
    function StringGetAsValue: TValue;
    procedure StringSetAsValue(value: TValue);
    function StringGetAsVariant: Variant;
    procedure StringSetAsVariant(value: Variant);
    function StringGetAsBitArray: TBitArray;
    procedure StringSetAsBitArray(value: TBitArray);
    function StringGetAsType<T>: T;
    procedure StringSetAsType<T>(value: T);
    function StringIsEmpty: boolean;
    function StringCompareTo(value: TAVValue): integer;
    function StringGetFormatedValue(FormatStr: string): string;
    procedure StringSetFormatedValue(FormatStr: string; value: string);
    procedure StringCopyFrom(value: TAVValue);
    procedure StringInitMethods;

//Byte
    function ByteGetAsString: string;
    procedure ByteSetAsString(value: string);
    function ByteGetAsInteger: integer;
    procedure ByteSetAsInteger(value: integer);
    function ByteGetAsInt64: Int64;
    procedure ByteSetAsInt64(value: Int64);
    function ByteGetAsDate: TDateTime;
    procedure ByteSetAsDate(value: TDateTime);
    function ByteGetAsBool: boolean;
    procedure ByteSetAsBool(value: boolean);
    function ByteGetAsFloat: double;
    procedure ByteSetAsFloat(value: double);
    function ByteGetAsObject: TObject;
    procedure ByteSetAsObject(value: TObject);
    function ByteGetAsValue: TValue;
    procedure ByteSetAsValue(value: TValue);
    function ByteGetAsVariant: Variant;
    procedure ByteSetAsVariant(value: Variant);
    function ByteGetAsBitArray: TBitArray;
    procedure ByteSetAsBitArray(value: TBitArray);
    function ByteGetAsType<T>: T;
    procedure ByteSetAsType<T>(value: T);
    function ByteIsEmpty: boolean;
    function ByteCompareTo(value: TAVValue): integer;
    function ByteGetFormatedValue(FormatStr: string): string;
    procedure ByteSetFormatedValue(FormatStr: string; value: string);
    procedure ByteCopyFrom(value: TAVValue);
    procedure ByteInitMethods;

//Int16
    function Int16GetAsString: string;
    procedure Int16SetAsString(value: string);
    function Int16GetAsInteger: integer;
    procedure Int16SetAsInteger(value: integer);
    function Int16GetAsInt64: Int64;
    procedure Int16SetAsInt64(value: Int64);
    function Int16GetAsDate: TDateTime;
    procedure Int16SetAsDate(value: TDateTime);
    function Int16GetAsBool: boolean;
    procedure Int16SetAsBool(value: boolean);
    function Int16GetAsFloat: double;
    procedure Int16SetAsFloat(value: double);
    function Int16GetAsObject: TObject;
    procedure Int16SetAsObject(value: TObject);
    function Int16GetAsValue: TValue;
    procedure Int16SetAsValue(value: TValue);
    function Int16GetAsVariant: Variant;
    procedure Int16SetAsVariant(value: Variant);
    function Int16GetAsBitArray: TBitArray;
    procedure Int16SetAsBitArray(value: TBitArray);
    function Int16GetAsType<T>: T;
    procedure Int16SetAsType<T>(value: T);
    function Int16IsEmpty: boolean;
    function Int16CompareTo(value: TAVValue): integer;
    function Int16GetFormatedValue(FormatStr: string): string;
    procedure Int16SetFormatedValue(FormatStr: string; value: string);
    procedure Int16CopyFrom(value: TAVValue);
    procedure Int16InitMethods;

//Int32
    function Int32GetAsString: string;
    procedure Int32SetAsString(value: string);
    function Int32GetAsInteger: integer;
    procedure Int32SetAsInteger(value: integer);
    function Int32GetAsInt64: Int64;
    procedure Int32SetAsInt64(value: Int64);
    function Int32GetAsDate: TDateTime;
    procedure Int32SetAsDate(value: TDateTime);
    function Int32GetAsBool: boolean;
    procedure Int32SetAsBool(value: boolean);
    function Int32GetAsFloat: double;
    procedure Int32SetAsFloat(value: double);
    function Int32GetAsObject: TObject;
    procedure Int32SetAsObject(value: TObject);
    function Int32GetAsValue: TValue;
    procedure Int32SetAsValue(value: TValue);
    function Int32GetAsVariant: Variant;
    procedure Int32SetAsVariant(value: Variant);
    function Int32GetAsBitArray: TBitArray;
    procedure Int32SetAsBitArray(value: TBitArray);
    function Int32GetAsType<T>: T;
    procedure Int32SetAsType<T>(value: T);
    function Int32IsEmpty: boolean;
    function Int32CompareTo(value: TAVValue): integer;
    function Int32GetFormatedValue(FormatStr: string): string;
    procedure Int32SetFormatedValue(FormatStr: string; value: string);
    procedure Int32CopyFrom(value: TAVValue);
    procedure Int32InitMethods;

//Int64
    function Int64GetAsString: string;
    procedure Int64SetAsString(value: string);
    function Int64GetAsInteger: integer;
    procedure Int64SetAsInteger(value: integer);
    function Int64GetAsInt64: Int64;
    procedure Int64SetAsInt64(value: Int64);
    function Int64GetAsDate: TDateTime;
    procedure Int64SetAsDate(value: TDateTime);
    function Int64GetAsBool: boolean;
    procedure Int64SetAsBool(value: boolean);
    function Int64GetAsFloat: double;
    procedure Int64SetAsFloat(value: double);
    function Int64GetAsObject: TObject;
    procedure Int64SetAsObject(value: TObject);
    function Int64GetAsValue: TValue;
    procedure Int64SetAsValue(value: TValue);
    function Int64GetAsVariant: Variant;
    procedure Int64SetAsVariant(value: Variant);
    function Int64GetAsBitArray: TBitArray;
    procedure Int64SetAsBitArray(value: TBitArray);
    function Int64GetAsType<T>: T;
    procedure Int64SetAsType<T>(value: T);
    function Int64IsEmpty: boolean;
    function Int64CompareTo(value: TAVValue): integer;
    function Int64GetFormatedValue(FormatStr: string): string;
    procedure Int64SetFormatedValue(FormatStr: string; value: string);
    procedure Int64CopyFrom(value: TAVValue);
    procedure Int64InitMethods;

//NativeInt
    function NativeIntGetAsString: string;
    procedure NativeIntSetAsString(value: string);
    function NativeIntGetAsInteger: integer;
    procedure NativeIntSetAsInteger(value: integer);
    function NativeIntGetAsInt64: Int64;
    procedure NativeIntSetAsInt64(value: Int64);
    function NativeIntGetAsDate: TDateTime;
    procedure NativeIntSetAsDate(value: TDateTime);
    function NativeIntGetAsBool: boolean;
    procedure NativeIntSetAsBool(value: boolean);
    function NativeIntGetAsFloat: double;
    procedure NativeIntSetAsFloat(value: double);
    function NativeIntGetAsObject: TObject;
    procedure NativeIntSetAsObject(value: TObject);
    function NativeIntGetAsValue: TValue;
    procedure NativeIntSetAsValue(value: TValue);
    function NativeIntGetAsVariant: Variant;
    procedure NativeIntSetAsVariant(value: Variant);
    function NativeIntGetAsBitArray: TBitArray;
    procedure NativeIntSetAsBitArray(value: TBitArray);
    function NativeIntGetAsType<T>: T;
    procedure NativeIntSetAsType<T>(value: T);
    function NativeIntIsEmpty: boolean;
    function NativeIntCompareTo(value: TAVValue): integer;
    function NativeIntGetFormatedValue(FormatStr: string): string;
    procedure NativeIntSetFormatedValue(FormatStr: string; value: string);
    procedure NativeIntCopyFrom(value: TAVValue);
    procedure NativeIntInitMethods;

//Float
    function FloatGetAsString: string;
    procedure FloatSetAsString(value: string);
    function FloatGetAsInteger: integer;
    procedure FloatSetAsInteger(value: integer);
    function FloatGetAsInt64: Int64;
    procedure FloatSetAsInt64(value: Int64);
    function FloatGetAsDate: TDateTime;
    procedure FloatSetAsDate(value: TDateTime);
    function FloatGetAsBool: boolean;
    procedure FloatSetAsBool(value: boolean);
    function FloatGetAsFloat: double;
    procedure FloatSetAsFloat(value: double);
    function FloatGetAsObject: TObject;
    procedure FloatSetAsObject(value: TObject);
    function FloatGetAsValue: TValue;
    procedure FloatSetAsValue(value: TValue);
    function FloatGetAsVariant: Variant;
    procedure FloatSetAsVariant(value: Variant);
    function FloatGetAsBitArray: TBitArray;
    procedure FloatSetAsBitArray(value: TBitArray);
    function FloatGetAsType<T>: T;
    procedure FloatSetAsType<T>(value: T);
    function FloatIsEmpty: boolean;
    function FloatCompareTo(value: TAVValue): integer;
    function FloatGetFormatedValue(FormatStr: string): string;
    procedure FloatSetFormatedValue(FormatStr: string; value: string);
    procedure FloatCopyFrom(value: TAVValue);
    procedure FloatInitMethods;

//Object
    function ObjectGetAsString: string;
    procedure ObjectSetAsString(value: string);
    function ObjectGetAsInteger: integer;
    procedure ObjectSetAsInteger(value: integer);
    function ObjectGetAsInt64: Int64;
    procedure ObjectSetAsInt64(value: Int64);
    function ObjectGetAsDate: TDateTime;
    procedure ObjectSetAsDate(value: TDateTime);
    function ObjectGetAsBool: boolean;
    procedure ObjectSetAsBool(value: boolean);
    function ObjectGetAsFloat: double;
    procedure ObjectSetAsFloat(value: double);
    function ObjectGetAsObject: TObject;
    procedure ObjectSetAsObject(value: TObject);
    function ObjectGetAsValue: TValue;
    procedure ObjectSetAsValue(value: TValue);
    function ObjectGetAsVariant: Variant;
    procedure ObjectSetAsVariant(value: Variant);
    function ObjectGetAsBitArray: TBitArray;
    procedure ObjectSetAsBitArray(value: TBitArray);
    function ObjectGetAsType<T>: T;
    procedure ObjectSetAsType<T>(value: T);
    function ObjectIsEmpty: boolean;
    function ObjectCompareTo(value: TAVValue): integer;
    function ObjectGetFormatedValue(FormatStr: string): string;
    procedure ObjectSetFormatedValue(FormatStr: string; value: string);
    procedure ObjectCopyFrom(value: TAVValue);
    procedure ObjectInitMethods;

//Date
    function DateGetAsString: string;
    procedure DateSetAsString(value: string);
    function DateGetAsInteger: integer;
    procedure DateSetAsInteger(value: integer);
    function DateGetAsInt64: Int64;
    procedure DateSetAsInt64(value: Int64);
    function DateGetAsDate: TDateTime;
    procedure DateSetAsDate(value: TDateTime);
    function DateGetAsBool: boolean;
    procedure DateSetAsBool(value: boolean);
    function DateGetAsFloat: double;
    procedure DateSetAsFloat(value: double);
    function DateGetAsObject: TObject;
    procedure DateSetAsObject(value: TObject);
    function DateGetAsValue: TValue;
    procedure DateSetAsValue(value: TValue);
    function DateGetAsVariant: Variant;
    procedure DateSetAsVariant(value: Variant);
    function DateGetAsBitArray: TBitArray;
    procedure DateSetAsBitArray(value: TBitArray);
    function DateGetAsType<T>: T;
    procedure DateSetAsType<T>(value: T);
    function DateIsEmpty: boolean;
    function DateCompareTo(value: TAVValue): integer;
    function DateGetFormatedValue(FormatStr: string): string;
    procedure DateSetFormatedValue(FormatStr: string; value: string);
    procedure DateCopyFrom(value: TAVValue);
    procedure DateInitMethods;

//Bool
    function BoolGetAsString: string;
    procedure BoolSetAsString(value: string);
    function BoolGetAsInteger: integer;
    procedure BoolSetAsInteger(value: integer);
    function BoolGetAsInt64: Int64;
    procedure BoolSetAsInt64(value: Int64);
    function BoolGetAsDate: TDateTime;
    procedure BoolSetAsDate(value: TDateTime);
    function BoolGetAsBool: boolean;
    procedure BoolSetAsBool(value: boolean);
    function BoolGetAsFloat: double;
    procedure BoolSetAsFloat(value: double);
    function BoolGetAsObject: TObject;
    procedure BoolSetAsObject(value: TObject);
    function BoolGetAsValue: TValue;
    procedure BoolSetAsValue(value: TValue);
    function BoolGetAsVariant: Variant;
    procedure BoolSetAsVariant(value: Variant);
    function BoolGetAsBitArray: TBitArray;
    procedure BoolSetAsBitArray(value: TBitArray);
    function BoolGetAsType<T>: T;
    procedure BoolSetAsType<T>(value: T);
    function BoolIsEmpty: boolean;
    function BoolCompareTo(value: TAVValue): integer;
    function BoolGetFormatedValue(FormatStr: string): string;
    procedure BoolSetFormatedValue(FormatStr: string; value: string);
    procedure BoolCopyFrom(value: TAVValue);
    procedure BoolInitMethods;

//TValue
    function ValueGetAsString: string;
    procedure ValueSetAsString(value: string);
    function ValueGetAsInteger: integer;
    procedure ValueSetAsInteger(value: integer);
    function ValueGetAsInt64: Int64;
    procedure ValueSetAsInt64(value: Int64);
    function ValueGetAsDate: TDateTime;
    procedure ValueSetAsDate(value: TDateTime);
    function ValueGetAsBool: boolean;
    procedure ValueSetAsBool(value: boolean);
    function ValueGetAsFloat: double;
    procedure ValueSetAsFloat(value: double);
    function ValueGetAsObject: TObject;
    procedure ValueSetAsObject(value: TObject);
    function ValueGetAsValue: TValue;
    procedure ValueSetAsValue(value: TValue);
    function ValueGetAsVariant: Variant;
    procedure ValueSetAsVariant(value: Variant);
    function ValueGetAsBitArray: TBitArray;
    procedure ValueSetAsBitArray(value: TBitArray);
    function ValueGetAsType<T>: T;
    procedure ValueSetAsType<T>(value: T);
    function ValueIsEmpty: boolean;
    function ValueCompareTo(value: TAVValue): integer;
    function ValueGetFormatedValue(FormatStr: string): string;
    procedure ValueSetFormatedValue(FormatStr: string; value: string);
    procedure ValueCopyFrom(value: TAVValue);
    procedure ValueInitMethods;

//Variant
    function VariantGetAsString: string;
    procedure VariantSetAsString(value: string);
    function VariantGetAsInteger: integer;
    procedure VariantSetAsInteger(value: integer);
    function VariantGetAsInt64: Int64;
    procedure VariantSetAsInt64(value: Int64);
    function VariantGetAsDate: TDateTime;
    procedure VariantSetAsDate(value: TDateTime);
    function VariantGetAsBool: boolean;
    procedure VariantSetAsBool(value: boolean);
    function VariantGetAsFloat: double;
    procedure VariantSetAsFloat(value: double);
    function VariantGetAsObject: TObject;
    procedure VariantSetAsObject(value: TObject);
    function VariantGetAsValue: TValue;
    procedure VariantSetAsValue(value: TValue);
    function VariantGetAsVariant: Variant;
    procedure VariantSetAsVariant(value: Variant);
    function VariantGetAsBitArray: TBitArray;
    procedure VariantSetAsBitArray(value: TBitArray);
    function VariantGetAsType<T>: T;
    procedure VariantSetAsType<T>(value: T);
    function VariantIsEmpty: boolean;
    function VariantCompareTo(value: TAVValue): integer;
    function VariantGetFormatedValue(FormatStr: string): string;
    procedure VariantSetFormatedValue(FormatStr: string; value: string);
    procedure VariantCopyFrom(value: TAVValue);
    procedure VariantInitMethods;

//BitArray
    function BitArrayGetAsString: string;
    procedure BitArraySetAsString(value: string);
    function BitArrayGetAsInteger: integer;
    procedure BitArraySetAsInteger(value: integer);
    function BitArrayGetAsInt64: Int64;
    procedure BitArraySetAsInt64(value: Int64);
    function BitArrayGetAsDate: TDateTime;
    procedure BitArraySetAsDate(value: TDateTime);
    function BitArrayGetAsBool: boolean;
    procedure BitArraySetAsBool(value: boolean);
    function BitArrayGetAsFloat: double;
    procedure BitArraySetAsFloat(value: double);
    function BitArrayGetAsObject: TObject;
    procedure BitArraySetAsObject(value: TObject);
    function BitArrayGetAsValue: TValue;
    procedure BitArraySetAsValue(value: TValue);
    function BitArrayGetAsVariant: Variant;
    procedure BitArraySetAsVariant(value: Variant);
    function BitArrayGetAsBitArray: TBitArray;
    procedure BitArraySetAsBitArray(value: TBitArray);
    function BitArrayGetAsType<T>: T;
    procedure BitArraySetAsType<T>(value: T);
    function BitArrayIsEmpty: boolean;
    function BitArrayCompareTo(value: TAVValue): integer;
    function BitArrayGetFormatedValue(FormatStr: string): string;
    procedure BitArraySetFormatedValue(FormatStr: string; value: string);
    procedure BitArrayCopyFrom(value: TAVValue);
    procedure BitArrayInitMethods;

//Record
    function RecordGetAsString: string;
    procedure RecordSetAsString(value: string);
    function RecordGetAsInteger: integer;
    procedure RecordSetAsInteger(value: integer);
    function RecordGetAsInt64: Int64;
    procedure RecordSetAsInt64(value: Int64);
    function RecordGetAsDate: TDateTime;
    procedure RecordSetAsDate(value: TDateTime);
    function RecordGetAsBool: boolean;
    procedure RecordSetAsBool(value: boolean);
    function RecordGetAsFloat: double;
    procedure RecordSetAsFloat(value: double);
    function RecordGetAsObject: TObject;
    procedure RecordSetAsObject(value: TObject);
    function RecordGetAsValue: TValue;
    procedure RecordSetAsValue(value: TValue);
    function RecordGetAsVariant: Variant;
    procedure RecordSetAsVariant(value: Variant);
    function RecordGetAsBitArray: TBitArray;
    procedure RecordSetAsBitArray(value: TBitArray);
    function RecordGetAsType<T>: T;
    procedure RecordSetAsType<T>(value: T);
    function RecordIsEmpty: boolean;
    function RecordCompareTo(value: TAVValue): integer;
    function RecordGetFormatedValue(FormatStr: string): string;
    procedure RecordSetFormatedValue(FormatStr: string; value: string);
    procedure RecordCopyFrom(value: TAVValue);
    procedure RecordInitMethods;

{$ENDREGION}

  public
    procedure PointTo<T>(pvalue: Pointer); overload;
    procedure PointTo<T>(var value: T); overload;
    procedure PointToNewValue(pv: Pointer); overload; inline;

    procedure CopyFrom(value: TAVValue);
    function IsEmpty: boolean;
    function CompareTo(value: TAVValue): integer;

    function GetAsType<T>: T;
    procedure SetAsType<T>(value: T);

    property AsString: string read GetAsString write SetAsString;
    property AsInteger: integer read GetAsInteger write SetAsInteger;
    property AsInt64: Int64 read GetAsInt64 write SetAsInt64;
    property AsDate: TDateTime read GetAsDate write SetAsDate;
    property AsBool: boolean read GetAsBool write SetAsBool;
    property AsFloat: double read GetAsFloat write SetAsFloat;
    property AsObject: TObject read GetAsObject write SetAsObject;
    property AsValue: TValue read GetAsValue write SetAsValue;
    property AsVariant: Variant read GetAsVariant write SetAsVariant;
    property AsBitArray: TBitArray read GetAsBitArray write SetAsBitArray;
    property AsRtti: TAVRttiObj read GetAsRtti;
    property FormatedValue[FormatStr: string]: string read GetFormatedValue write SetFormatedValue;

    property ValueType: TAVType read GetValueType;
  end;

{$REGION 'Generics'}

type
  TAction<T> = procedure(p: T) of object;
  TFunc<T> = function: T;
  TProc<T> = reference to procedure(p: T);
  TParameterizedProc<T> = reference to procedure(proc: T; args: TArray<TValue>);

  TEvent<T> = record
  private
    list: TArray<T>;
    fExecuteProc: TParameterizedProc<T>;
    FComparer: IComparer<T>;
    function IndexOf(proc: T): integer;
  public
    constructor Create(proc: TParameterizedProc<T>);

    procedure Add(proc: T);
    procedure Remove(proc: T);
    function HasMember: boolean;
    procedure Execute(args: TArray<TValue>);
  end;

{$ENDREGION}

type

  PTAVProperty = ^TAVProperty;
  TAVProperty = record
    Name: string;
    Value: TValue;
  end;

  TAVProperties = class(TObject)
  private
    fList: TList<TAVProperty>;
    fValue: TAVValue;
    function FindByName(Name: string): PTAVProperty;
    function GetValue(Name: string): TAVValue;
  public
    constructor Create;
    destructor Destroy; override;

    property Value[Name: string]: TAVValue read GetValue; default;
  end;

function TryAVTypeFromTypeInfo(typeInfo: PTypeInfo; var avType: TAVType): boolean;
function AVTypeFromTypeInfo(typeInfo: PTypeInfo): TAVType;

implementation
uses AVUtils;

var
  fContextCreated: boolean = false;
  fContext: TRttiContext;

function RttiContext: TRttiContext;
begin
  if not fContextCreated then begin
    fContext := TRttiContext.Create;
    fContextCreated := true;
  end;
  Result := fContext;
end;

// TBitArray

procedure TBitArray.Clear;
begin
  SetLength(fData, 0);
end;

function TBitArray.GetByteIndex(index: integer): integer;
begin
  Result := index div 8;
end;

function TBitArray.GetBitIndex(index: integer): integer;
begin
  Result := index mod 8;
end;

function TBitArray.GetByteCount: integer;
begin
  Result := Length(fData);
end;

procedure TBitArray.SetByteCount(value: integer);
var
  oldLength: integer;
begin
  oldLength := Length(fData);
  SetLength(fData, value);
  if oldLength < value then FillChar(fData[oldLength], value - oldLength, 0);
end;

procedure TBitArray.PrepareSize(ByteIndex: integer);
var
  size: integer;
begin
  size := Length(fData);
  if (size < ByteIndex + 1) then
  begin
    SetLength(fData, ByteIndex + 1);
    FillChar(fData[size], ByteIndex + 1 - size, 0);
  end;
end;

function TBitArray.GetByte(index: integer): byte;
begin
  PrepareSize(index);
  Result := fData[index];
end;

procedure TBitArray.SetByte(index: integer; value: byte);
begin
  PrepareSize(index);
  fData[index] := value;
end;

function TBitArray.GetByteBit(ByteIndex, BitIndex: integer): boolean;
begin
  Result := (GetByte(ByteIndex) and Bits[BitIndex]) > 0;
end;

procedure TBitArray.SetByteBit(ByteIndex, BitIndex: integer; value: boolean);
begin
  if value then
    SetByte(ByteIndex, GetByte(ByteIndex) or Bits[BitIndex])
  else
    SetByte(ByteIndex, GetByte(ByteIndex) and NegBits[BitIndex]);
end;

function TBitArray.GetBit(index: integer): boolean;
begin
  Result := GetByteBit(GetByteIndex(index), GetBitIndex(index));
end;

procedure TBitArray.SetBit(index: integer; value: boolean);
begin
  SetByteBit(GetByteIndex(index), GetBitIndex(index), value);
end;

procedure TBitArray.GetData(var Buffer; BufferSize: integer);
begin
  PrepareSize(BufferSize - 1);
  Move(fData[0], Buffer, BufferSize);
end;

procedure TBitArray.SetData(var Buffer; BufferSize: integer);
begin
  PrepareSize(BufferSize - 1);
  Move(Buffer, fData[0], BufferSize);
end;

function TBitArray.GetCount: integer;
begin
  Result := Length(fData) * 8;
end;

function TBitArray.GetAsString: string;
var i: integer;
    b: System.byte;
begin
  SetLength(Result, ByteCount*2);
  for i := 0 to ByteCount - 1 do begin
    b := byte[i];
    Result[i*2 + 2] := HexChars[b and ByteHalfs[0]];
    Result[i*2 + 1] := HexChars[(b shr 4)];
  end;
end;

procedure TBitArray.SetAsString(value: string);
var s: string;
    skiped, i: integer;

    function HexCharToByte(ch: Char): System.byte; inline;
    begin
      if (ch >= '0') and (ch <= '9')
        then Result := Ord(ch) - Ord('0')
        else Result := Ord(ch) - Ord('A') + 10;
    end;
begin
  value := UpperCase(value);
  skiped := 0;
  SetLength(s, length(value));
  for i := 1 to length(value) do
    if CharInSet(value[i], HexCharsSet)
      then s[i - skiped] := value[i]
      else Inc(skiped);
  SetLength(s, length(value)-skiped);
  if (Length(s) > 0) and ((Length(s) mod 2) <> 0) then SetLength(s, length(s) - 1);

  ByteCount := Length(s) div 2;
  i := 1;
  while i < length(s) do begin
    byte[i div 2] := (HexCharToByte(s[i]) shl 4) + HexCharToByte(s[i + 1]);
    Inc(i, 2);
  end;
end;

// TAVRttiObj

class operator TAVRttiObj.Explicit(obj: TObject): TAVRttiObj;
begin
  Result.Instance := obj;
  Result.TypeInfo := obj.ClassInfo;
  Result.fFieldsInited := false;
  Result.fPropsInited := false;
end;

function TAVRttiObj.GetItem(ForInstance: Pointer; ForTypeInfo: PTypeInfo; Path: string): TValue;
var
  fType: TRttiType;
  fField: TRttiField;
  fProp: TRttiProperty;
  fMethod: TRttiMethod;
  s1, s2: string;
  v: TValue;
  obj: TObject;
begin
  if Instance = nil then exit;

  SplitTwo(Path, '.', s1, s2);

  fType := RttiContext.GetType(ForTypeInfo);
  if fType <> nil then
  begin
    fField := fType.GetField(s1);
    if fField <> nil then
      v := fField.GetValue(ForInstance)
    else
    begin
      fProp := fType.GetProperty(s1);
      if (fProp <> nil) and fProp.IsReadable then
        v := fProp.GetValue(ForInstance)
      else
      begin
        fMethod := fType.GetMethod(s1);
        if (fMethod <> nil) and (Length(fMethod.GetParameters) = 0) then
          v := fMethod.Invoke(ForInstance, [])
        else
          raise Exception.CreateRes(@SInvalidPropertyPath);
      end;
    end;
  end
  else
    raise Exception.CreateRes(@SObjectRequired);

  if (s2 <> '') then
  begin
    obj := v.AsObject;
    Result := GetItem(obj, obj.ClassInfo, s2);
  end
  else
    Result := v;
end;

procedure TAVRttiObj.SetItem(ForInstance: Pointer; ForTypeInfo: PTypeInfo; Path: string; value: TValue);
var
  fType: TRttiType;
  fField: TRttiField;
  fProp: TRttiProperty;
  fMethod: TRttiMethod;
  s1, s2: string;
  obj: TObject;
begin
  if Instance = nil then exit;

  SplitTwo(Path, '.', s1, s2);

  if s2 <> '' then begin
    obj := GetItem(ForInstance, ForTypeInfo, s1).AsObject;
    SetItem(obj, obj.ClassInfo, s2, value);
  end else begin
    fType := RttiContext.GetType(ForTypeInfo);
    if fType <> nil then
    begin
      fField := fType.GetField(s1);
      if fField <> nil then
        fField.SetValue(ForInstance, value)
      else
      begin
        fProp := fType.GetProperty(s1);
        if (fProp <> nil) and fProp.IsWritable then
          fProp.SetValue(ForInstance, value)
        else
        begin
          fMethod := fType.GetMethod(s1);
          if (fMethod <> nil) and (Length(fMethod.GetParameters) = 1) then
            fMethod.Invoke(ForInstance, [value])
          else
            raise Exception.CreateRes(@SInvalidPropertyPath);
        end;
      end;
    end
    else
      raise Exception.CreateRes(@SObjectRequired);
  end;
end;

function TAVRttiObj.GetItem(Path: string): TValue;
begin
  Result := GetItem(Instance, TypeInfo, Path);
end;

procedure TAVRttiObj.SetItem(Path: string; value: TValue);
begin
  SetItem(Instance, TypeInfo, Path, value);
end;

function TAVRttiObj.Invoke(Method: string; params: array of TValue): TValue;
var
  fType: TRttiType;
  fMethod: TRttiMethod;
begin
  if Instance = nil then exit;

  fType := RttiContext.GetType(TypeInfo);
  if (fType <> nil) then begin
    fMethod := fType.GetMethod(Method);
    if fMethod = nil then raise Exception.CreateResFmt(@SMethodNotFound, [Method]);
    Result := fMethod.Invoke(Instance, params);
  end else raise Exception.CreateRes(@SObjectRequired);
end;

function TAVRttiObj.GetFields: TArray<TRttiField>;
var
  fType: TRttiType;
begin
  if not fFieldsInited and (Instance <> nil) then begin
    fType := RttiContext.GetType(TypeInfo);
    if (fType <> nil) then begin
      fFields := fType.GetFields;
    end;
    fFieldsInited := true;
  end;
  Result := fFields;
end;

function TAVRttiObj.GetProperties: TArray<TRttiProperty>;
var
  fType: TRttiType;
begin
  if not fPropsInited and (Instance <> nil) then begin
    fType := RttiContext.GetType(TypeInfo);
    if (fType <> nil) then begin
      fProps := fType.GetProperties;
    end;
    fPropsInited := true;
  end;
  Result := fProps;
end;

//TEvent<T>

constructor TEvent<T>.Create(proc: TParameterizedProc<T>);
begin
  fExecuteProc := proc;
  FComparer := TComparer<T>.Default;
end;

function TEvent<T>.HasMember: boolean;
begin
  Result := Length(list) > 0;
end;

procedure TEvent<T>.Execute(args: TArray<TValue>);
var i: integer;
begin
  for i := Low(list) to High(list) do
    fExecuteProc(list[i], args);
end;

procedure TEvent<T>.Add(proc: T);
begin
  SetLength(list, Length(list) + 1);
  list[Length(list) - 1] := proc;
end;

function TEvent<T>.IndexOf(proc: T): integer;
var i: integer;
begin
  for i := Low(list) to High(list) do
    if FComparer.Compare(list[i], proc) = 0 then Exit(i);
end;

procedure TEvent<T>.Remove(proc: T);
var n: integer;
begin
  n := IndexOf(proc);
  if n >= 0 then begin
    System.Move(list[n + 1], list[n], (Length(list) - n) * SizeOf(T));
    SetLength(list, Length(list) - 1);
  end;
end;

//TAVProperties

constructor TAVProperties.Create;
begin
  inherited Create;
  fList := TList<TAVProperty>.Create;
  fValue := TAVValue.Create;
  fValue.PointTo<TValue>(nil);
end;

destructor TAVProperties.Destroy;
begin
  fList.Free;
  fValue.Free;
  inherited Destroy;
end;

function TAVProperties.FindByName(Name: string): PTAVProperty;
var i: integer;
begin
  Result := nil;
  for i := 0 to fList.Count - 1 do
    if CompareText(fList[i].Name, Name) = 0 then Exit(@(fList.List[i]));
end;

function TAVProperties.GetValue(Name: string): TAVValue;
var P: PTAVProperty;
    Prop: TAVProperty;
begin
  P := FindByName(Name);
  if P = nil then begin
    Prop.Name := Name;
    fList.Add(Prop);
    P := @(fList.List[fList.Count - 1]);
  end;
  fValue.PointToNewValue(@(P^.Value));
  Result := fValue;
end;

//----------------------

function TryAVTypeFromTypeInfo(typeInfo: PTypeInfo; var avType: TAVType): boolean;
begin
  Result := true;
  if typeInfo = System.TypeInfo(TValue) then begin avType := avtValue; exit; end;
  if typeInfo = System.TypeInfo(NativeInt) then begin avType := avtNativeInt; exit; end;
  if typeInfo = System.TypeInfo(boolean) then begin avType := avtBool; exit; end;
  if typeInfo = System.TypeInfo(TBitArray) then begin avType := avtBitArray; exit; end;
  case TypeInfo^.Kind of
    tkInteger, tkEnumeration, tkChar, tkWChar, tkSet:
      case GetTypeData(TypeInfo)^.OrdType of
        otSByte, otUByte: begin avType := avtByte; exit; end;
        otSWord, otUWord: begin avType := avtInt16; exit; end;
        otSLong, otULong: begin avType := avtInt32; exit; end;
      else
        Result := false;
        exit;
      end;
    tkFloat:
      case GetTypeData(TypeInfo)^.FloatType of
        ftDouble: begin
                    if (TypeInfo^.Name = 'TDateTime') then begin avType := avtDate; exit; end;
                    avType := avtDouble;
                    exit;
                  end;
        ftComp: begin avType := avtDouble; exit; end;
        ftCurr: begin avType := avtDouble; exit; end;
      else
        Result := false;
        exit;
      end;
    tkClass: begin avType := avtObject; exit; end;
    tkMethod: begin avType := avtRecord; exit; end;
    tkInt64: begin avType := avtInt64; exit; end;
    tkUString: begin avType := avtString; exit; end;
{$IFNDEF NEXTGEN}
    tkString: begin avType := avtString; exit; end;
{$ENDIF !NEXTGEN}
    tkRecord: begin avType := avtRecord; exit; end;
    tkVariant: begin avType := avtVariant; exit; end;
  else
    Result := false;
    exit;
  end;
end;

function AVTypeFromTypeInfo(typeInfo: PTypeInfo): TAVType;
begin
  if not TryAVTypeFromTypeInfo(typeInfo, Result) then
    raise Exception.CreateRes(@SUnsupportedType);
end;

{$REGION 'Typed methods'}

//String
function TAVValue.StringGetAsString: string;
begin
  Result := PAVString(VInfo.PValue)^;
end;

procedure TAVValue.StringSetAsString(value: string);
begin
  PAVString(VInfo.PValue)^ := value;
end;

function TAVValue.StringGetAsInteger: integer;
begin
  Result := StrToIntAnyway(PAVString(VInfo.PValue)^);
end;

procedure TAVValue.StringSetAsInteger(value: integer);
begin
  PAVString(VInfo.PValue)^ := IntToStr(value);
end;

function TAVValue.StringGetAsInt64: Int64;
begin
  Result := StrToIntAnyway(PAVString(VInfo.PValue)^);
end;

procedure TAVValue.StringSetAsInt64(value: Int64);
begin
  PAVString(VInfo.PValue)^ := IntToStr(value);
end;

function TAVValue.StringGetAsDate: TDateTime;
begin
  Result := StrToDateTimeAnyway(PAVString(VInfo.PValue)^);
end;

procedure TAVValue.StringSetAsDate(value: TDateTime);
begin
  PAVString(VInfo.PValue)^ := DateTimeToStr(value);
end;

function TAVValue.StringGetAsBool: boolean;
begin
  Result := StrToBoolAnyway(PAVString(VInfo.PValue)^);
end;

procedure TAVValue.StringSetAsBool(value: boolean);
begin
  PAVString(VInfo.PValue)^ := AVUtils.BoolToStr(value);
end;

function TAVValue.StringGetAsFloat: double;
begin
  Result := StrToFloatAnyway(PAVString(VInfo.PValue)^);
end;

procedure TAVValue.StringSetAsFloat(value: double);
begin
  PAVString(VInfo.PValue)^ := FloatToStr(value);
end;

function TAVValue.StringGetAsObject: TObject;
begin
  Result := nil;
end;

procedure TAVValue.StringSetAsObject(value: TObject);
begin
  if (value <> nil)
    then PAVString(VInfo.PValue)^ := value.ToString;
end;

function TAVValue.StringGetAsValue: TValue;
begin
  Result := TValue.From<string>(PAVString(VInfo.PValue)^);
end;

procedure TAVValue.StringSetAsValue(value: TValue);
begin
  case value.TypeInfo^.Kind of
    tkChar, tkString, tkWChar, tkLString, tkWString, tkUString:
      PAVString(VInfo.PValue)^ := value.AsString;
    tkInteger, tkInt64:
      PAVString(VInfo.PValue)^ := IntToStr(value.AsOrdinal);
    tkFloat:
      PAVString(VInfo.PValue)^ := FloatToStr(value.AsExtended);
    else
      begin
        try
          PAVString(VInfo.PValue)^ := value.AsString;
        except
          PAVString(VInfo.PValue)^ := '';
        end;
      end;
    end;
end;

function TAVValue.StringGetAsVariant: Variant;
begin
  Result := PAVString(VInfo.PValue)^;
end;

procedure TAVValue.StringSetAsVariant(value: Variant);
begin
  case TVarData(value).VType of
    varOleStr, varStrArg, varString:
      PAVString(VInfo.PValue)^ := value;
    varSmallint, varInteger, varShortInt, varByte, varWord, varLongWord,
      varInt64:
      PAVString(VInfo.PValue)^ := IntToStr(value);
    varSingle, varDouble, varCurrency:
      PAVString(VInfo.PValue)^ := FloatToStr(value);
    varDate:
      PAVString(VInfo.PValue)^ := DateTimeToStr(value);
    varBoolean:
      PAVString(VInfo.PValue)^ := AVUtils.BoolToStr(value);
    else
      begin
        try
          PAVString(VInfo.PValue)^ := value;
        except
          PAVString(VInfo.PValue)^ := '';
        end;
      end;
    end;
end;

function TAVValue.StringGetAsBitArray: TBitArray;
begin
  Result.AsString := PAVString(VInfo.PValue)^;
end;

procedure TAVValue.StringSetAsBitArray(value: TBitArray);
begin
  PAVString(VInfo.PValue)^ := value.AsString;
end;

function TAVValue.StringGetAsType<T>: T;
var v: TAVValue;
begin
  v.PointTo<T>(Result);
  v.AsString := PAVString(VInfo.PValue)^;
end;

procedure TAVValue.StringSetAsType<T>(value: T);
var v: TAVValue;
begin
  v.PointTo<T>(value);
  PAVString(VInfo.PValue)^ := v.AsString;
end;

function TAVValue.StringIsEmpty: boolean;
begin
  Result := PAVString(VInfo.PValue)^ = '';
end;

function TAVValue.StringGetFormatedValue(FormatStr: string): string;
begin
  Result := GetAsString;
end;

procedure TAVValue.StringSetFormatedValue(FormatStr: string; value: string);
begin
  SetAsString(value);
end;

procedure TAVValue.StringCopyFrom(value: TAVValue);
begin
  StringSetAsString(value.AsString);
end;

function TAVValue.StringCompareTo(value: TAVValue): integer;
begin
  Result := CompareText(PAVString(VInfo.PValue)^, value.AsString);
end;

procedure TAVValue.StringInitMethods;
begin
  fGetAsString := StringGetAsString;
  fSetAsString := StringSetAsString;
  fGetAsInteger := StringGetAsInteger;
  fSetAsInteger := StringSetAsInteger;
  fGetAsInt64 := StringGetAsInt64;
  fSetAsInt64 := StringSetAsInt64;
  fGetAsDate := StringGetAsDate;
  fSetAsDate := StringSetAsDate;
  fGetAsBool := StringGetAsBool;
  fSetAsBool := StringSetAsBool;
  fGetAsFloat := StringGetAsFloat;
  fSetAsFloat := StringSetAsFloat;
  fGetAsObject := StringGetAsObject;
  fSetAsObject := StringSetAsObject;
  fGetAsValue := StringGetAsValue;
  fSetAsValue := StringSetAsValue;
  fGetAsVariant := StringGetAsVariant;
  fSetAsVariant := StringSetAsVariant;
  fGetAsBitArray := StringGetAsBitArray;
  fSetAsBitArray := StringSetAsBitArray;
  fGetFormatedValue := StringGetFormatedValue;
  fSetFormatedValue := StringSetFormatedValue;
  fCopyFrom := StringCopyFrom;
  fIsEmpty := StringIsEmpty;
  fCompareTo := StringCompareTo;
end;

//Byte

function TAVValue.ByteGetAsString: string;
begin
  Result := IntToStr(PAVByte(VInfo.PValue)^);
end;

procedure TAVValue.ByteSetAsString(value: string);
begin
  PAVByte(VInfo.PValue)^ := StrToIntAnyway(value);
end;

function TAVValue.ByteGetAsInteger: integer;
begin
  Result := PAVByte(VInfo.PValue)^;
end;

procedure TAVValue.ByteSetAsInteger(value: integer);
begin
  PAVByte(VInfo.PValue)^ := value;
end;

function TAVValue.ByteGetAsInt64: Int64;
begin
  Result := PAVByte(VInfo.PValue)^;
end;

procedure TAVValue.ByteSetAsInt64(value: Int64);
begin
  PAVByte(VInfo.PValue)^ := value;
end;

function TAVValue.ByteGetAsDate: TDateTime;
begin
  Result := PAVByte(VInfo.PValue)^;
end;

procedure TAVValue.ByteSetAsDate(value: TDateTime);
begin
  PAVByte(VInfo.PValue)^ := Trunc(value);
end;

function TAVValue.ByteGetAsBool: boolean;
begin
  Result := PAVByte(VInfo.PValue)^ > 0;
end;

procedure TAVValue.ByteSetAsBool(value: boolean);
begin
  if value
    then PAVByte(VInfo.PValue)^ := 1
    else PAVByte(VInfo.PValue)^ := 0;
end;

function TAVValue.ByteGetAsFloat: double;
begin
  Result := PAVByte(VInfo.PValue)^;
end;

procedure TAVValue.ByteSetAsFloat(value: double);
begin
  PAVByte(VInfo.PValue)^ := Trunc(value);
end;

function TAVValue.ByteGetAsObject: TObject;
begin
  Result := nil;
end;

procedure TAVValue.ByteSetAsObject(value: TObject);
begin
  PAVByte(VInfo.PValue)^ := 0;
end;

function TAVValue.ByteGetAsValue: TValue;
begin
  Result := TValue.From<byte>(PAVByte(VInfo.PValue)^);
end;

procedure TAVValue.ByteSetAsValue(value: TValue);
var v: TValue;
begin
  case value.TypeInfo.Kind of
    tkInteger,
    tkEnumeration,
    tkInt64 : SetAsInt64(value.AsOrdinal);
    tkChar,
    tkWChar,
    tkString,
    tkLString,
    tkWString,
    tkUString : SetAsString(value.AsString);
    tkFloat : SetAsFloat(value.AsExtended);
    else
      if value.TryCast(TypeInfo(Int64), v)
        then SetAsInt64(v.AsInt64)
        else PAVByte(VInfo.PValue)^ := 0;
  end;
end;

function TAVValue.ByteGetAsVariant: Variant;
begin
  Result := PAVByte(VInfo.PValue)^;
end;

procedure TAVValue.ByteSetAsVariant(value: Variant);
begin
  case TVarData(value).VType of
    varSmallInt,
    varInteger,
    varSingle,
    varShortInt,
    varByte,
    varWord,
    varLongWord,
    varInt64,
    varUInt64: SetAsInt64(value);
    varDouble,
    varCurrency: SetAsFloat(value);
    varDate: SetAsDate(value);
    varOleStr,
    varString,
    varUString: SetAsString(value);
    varBoolean: SetAsBool(value);
    else
      try
        SetAsInt64(value);
      except
        PAVByte(VInfo.PValue)^ := 0;
      end;
  end;
end;

function TAVValue.ByteGetAsBitArray: TBitArray;
begin
  Result.SetData(PAVByte(VInfo.PValue)^, SizeOf(byte));
end;

procedure TAVValue.ByteSetAsBitArray(value: TBitArray);
begin
  value.GetData(PAVByte(VInfo.PValue)^, SizeOf(byte));
end;

function TAVValue.ByteGetAsType<T>: T;
var v: TAVValue;
begin
  v.PointTo<T>(Result);
  v.AsInteger := PAVByte(VInfo.PValue)^;
end;

procedure TAVValue.ByteSetAsType<T>(value: T);
var v: TAVValue;
begin
  v.PointTo<T>(value);
  PAVByte(VInfo.PValue)^ := v.AsInteger;
end;

function TAVValue.ByteIsEmpty: boolean;
begin
  Result := PAVByte(VInfo.PValue)^ = 0;
end;

function TAVValue.ByteCompareTo(value: TAVValue): integer;
begin
  Result := PAVByte(VInfo.PValue)^ - value.AsInteger;
end;

function TAVValue.ByteGetFormatedValue(FormatStr: string): string;
begin
  Result := Trim(Format(FormatStr, [GetAsInteger]));
end;

procedure TAVValue.ByteSetFormatedValue(FormatStr: string; value: string);
begin
  SetAsString(value);
end;

procedure TAVValue.ByteCopyFrom(value: TAVValue);
begin
  ByteSetAsInteger(value.AsInteger);
end;

procedure TAVValue.ByteInitMethods;
begin
  fGetAsString := ByteGetAsString;
  fSetAsString := ByteSetAsString;
  fGetAsInteger := ByteGetAsInteger;
  fSetAsInteger := ByteSetAsInteger;
  fGetAsInt64 := ByteGetAsInt64;
  fSetAsInt64 := ByteSetAsInt64;
  fGetAsDate := ByteGetAsDate;
  fSetAsDate := ByteSetAsDate;
  fGetAsBool := ByteGetAsBool;
  fSetAsBool := ByteSetAsBool;
  fGetAsFloat := ByteGetAsFloat;
  fSetAsFloat := ByteSetAsFloat;
  fGetAsObject := ByteGetAsObject;
  fSetAsObject := ByteSetAsObject;
  fGetAsValue := ByteGetAsValue;
  fSetAsValue := ByteSetAsValue;
  fGetAsVariant := ByteGetAsVariant;
  fSetAsVariant := ByteSetAsVariant;
  fGetAsBitArray := ByteGetAsBitArray;
  fSetAsBitArray := ByteSetAsBitArray;
  fGetFormatedValue := ByteGetFormatedValue;
  fSetFormatedValue := ByteSetFormatedValue;
  fCopyFrom := ByteCopyFrom;
  fIsEmpty := ByteIsEmpty;
  fCompareTo := ByteCompareTo;
end;

//Int16

function TAVValue.Int16GetAsString: string;
begin
  Result := IntToStr(PAVInt16(VInfo.PValue)^);
end;

procedure TAVValue.Int16SetAsString(value: string);
begin
  PAVInt16(VInfo.PValue)^ := StrToIntAnyway(value);
end;

function TAVValue.Int16GetAsInteger: integer;
begin
  Result := PAVInt16(VInfo.PValue)^;
end;

procedure TAVValue.Int16SetAsInteger(value: integer);
begin
  PAVInt16(VInfo.PValue)^ := value;
end;

function TAVValue.Int16GetAsInt64: Int64;
begin
  Result := PAVInt16(VInfo.PValue)^;
end;

procedure TAVValue.Int16SetAsInt64(value: Int64);
begin
  PAVInt16(VInfo.PValue)^ := value;
end;

function TAVValue.Int16GetAsDate: TDateTime;
begin
  Result := PAVInt16(VInfo.PValue)^;
end;

procedure TAVValue.Int16SetAsDate(value: TDateTime);
begin
  PAVInt16(VInfo.PValue)^ := Trunc(value);
end;

function TAVValue.Int16GetAsBool: boolean;
begin
  Result := PAVInt16(VInfo.PValue)^ <> 0;
end;

procedure TAVValue.Int16SetAsBool(value: boolean);
begin
  if value
    then PAVInt16(VInfo.PValue)^ := 1
    else PAVInt16(VInfo.PValue)^ := 0;
end;

function TAVValue.Int16GetAsFloat: double;
begin
  Result := PAVInt16(VInfo.PValue)^;
end;

procedure TAVValue.Int16SetAsFloat(value: double);
begin
  PAVInt16(VInfo.PValue)^ := Trunc(value);
end;

function TAVValue.Int16GetAsObject: TObject;
begin
  Result := nil
end;

procedure TAVValue.Int16SetAsObject(value: TObject);
begin
  PAVInt16(VInfo.PValue)^ := 0;
end;

function TAVValue.Int16GetAsValue: TValue;
begin
  Result := TValue.From<Int16>(PAVInt16(VInfo.PValue)^);
end;

procedure TAVValue.Int16SetAsValue(value: TValue);
begin
  PAVInt16(VInfo.PValue)^ := value.AsOrdinal;
end;

function TAVValue.Int16GetAsVariant: Variant;
begin
  Result := PAVInt16(VInfo.PValue)^;
end;

procedure TAVValue.Int16SetAsVariant(value: Variant);
begin
  PAVInt16(VInfo.PValue)^ := value;
end;

function TAVValue.Int16GetAsBitArray: TBitArray;
begin
  Result.SetData(PAVInt16(VInfo.PValue)^, SizeOf(Int16));
end;

procedure TAVValue.Int16SetAsBitArray(value: TBitArray);
begin
  value.GetData(PAVInt16(VInfo.PValue)^, SizeOf(Int16));
end;

function TAVValue.Int16GetAsType<T>: T;
var v: TAVValue;
begin
  v.PointTo<T>(Result);
  v.AsInteger := PAVInt16(VInfo.PValue)^;
end;

procedure TAVValue.Int16SetAsType<T>(value: T);
var v: TAVValue;
begin
  v.PointTo<T>(value);
  PAVInt16(VInfo.PValue)^ := v.AsInteger;
end;

function TAVValue.Int16IsEmpty: boolean;
begin
  Result := PAVInt16(VInfo.PValue)^ = 0;
end;

function TAVValue.Int16CompareTo(value: TAVValue): integer;
begin
  Result := PAVInt16(VInfo.PValue)^ - value.AsInteger;
end;

function TAVValue.Int16GetFormatedValue(FormatStr: string): string;
begin
  Result := Trim(Format(FormatStr, [GetAsInteger]));
end;

procedure TAVValue.Int16SetFormatedValue(FormatStr: string; value: string);
begin
  SetAsString(value);
end;

procedure TAVValue.Int16CopyFrom(value: TAVValue);
begin
  Int16SetAsInteger(value.AsInteger);
end;

procedure TAVValue.Int16InitMethods;
begin
  fGetAsString := Int16GetAsString;
  fSetAsString := Int16SetAsString;
  fGetAsInteger := Int16GetAsInteger;
  fSetAsInteger := Int16SetAsInteger;
  fGetAsInt64 := Int16GetAsInt64;
  fSetAsInt64 := Int16SetAsInt64;
  fGetAsDate := Int16GetAsDate;
  fSetAsDate := Int16SetAsDate;
  fGetAsBool := Int16GetAsBool;
  fSetAsBool := Int16SetAsBool;
  fGetAsFloat := Int16GetAsFloat;
  fSetAsFloat := Int16SetAsFloat;
  fGetAsObject := Int16GetAsObject;
  fSetAsObject := Int16SetAsObject;
  fGetAsValue := Int16GetAsValue;
  fSetAsValue := Int16SetAsValue;
  fGetAsVariant := Int16GetAsVariant;
  fSetAsVariant := Int16SetAsVariant;
  fGetAsBitArray := Int16GetAsBitArray;
  fSetAsBitArray := Int16SetAsBitArray;
  fGetFormatedValue := Int16GetFormatedValue;
  fSetFormatedValue := Int16SetFormatedValue;
  fCopyFrom := Int16CopyFrom;
  fIsEmpty := Int16IsEmpty;
  fCompareTo := Int16CompareTo;
end;

//Int32

function TAVValue.Int32GetAsString: string;
begin
  Result := IntToStr(PAVInt32(VInfo.PValue)^);
end;

procedure TAVValue.Int32SetAsString(value: string);
begin
  PAVInt32(VInfo.PValue)^ := StrToIntAnyway(value);
end;

function TAVValue.Int32GetAsInteger: integer;
begin
  Result := PAVInt32(VInfo.PValue)^;
end;

procedure TAVValue.Int32SetAsInteger(value: integer);
begin
  PAVInt32(VInfo.PValue)^ := value;
end;

function TAVValue.Int32GetAsInt64: Int64;
begin
  Result := PAVInt32(VInfo.PValue)^;
end;

procedure TAVValue.Int32SetAsInt64(value: Int64);
begin
  PAVInt32(VInfo.PValue)^ := value;
end;

function TAVValue.Int32GetAsDate: TDateTime;
begin
  Result := PAVInt32(VInfo.PValue)^;
end;

procedure TAVValue.Int32SetAsDate(value: TDateTime);
begin
  PAVInt32(VInfo.PValue)^ := Trunc(value);
end;

function TAVValue.Int32GetAsBool: boolean;
begin
  Result := PAVInt32(VInfo.PValue)^ <> 0;
end;

procedure TAVValue.Int32SetAsBool(value: boolean);
begin
  if value
    then PAVInt32(VInfo.PValue)^ := 1
    else PAVInt32(VInfo.PValue)^ := 0;
end;

function TAVValue.Int32GetAsFloat: double;
begin
  Result := PAVInt32(VInfo.PValue)^;
end;

procedure TAVValue.Int32SetAsFloat(value: double);
begin
  PAVInt32(VInfo.PValue)^ := Trunc(value);
end;

function TAVValue.Int32GetAsObject: TObject;
begin
{$IFDEF CPUX64}
  Result := nil;
{$ELSE}
  Result := Pointer(PAVInt32(VInfo.PValue)^);
{$ENDIF}
end;

procedure TAVValue.Int32SetAsObject(value: TObject);
begin
{$IFDEF CPUX64}
  PAVInt32(VInfo.PValue)^ := 0;
{$ELSE}
  PAVInt32(VInfo.PValue)^ := Integer(value);
{$ENDIF}
end;

function TAVValue.Int32GetAsValue: TValue;
begin
  Result := TValue.From<Int32>(PAVInt32(VInfo.PValue)^);
end;

procedure TAVValue.Int32SetAsValue(value: TValue);
begin
  PAVInt32(VInfo.PValue)^ := value.AsOrdinal;
end;

function TAVValue.Int32GetAsVariant: Variant;
begin
  Result := PAVInt32(VInfo.PValue)^;
end;

procedure TAVValue.Int32SetAsVariant(value: Variant);
begin
  PAVInt32(VInfo.PValue)^ := value;
end;

function TAVValue.Int32GetAsBitArray: TBitArray;
begin
  Result.SetData(PAVInt32(VInfo.PValue)^, SizeOf(Int32));
end;

procedure TAVValue.Int32SetAsBitArray(value: TBitArray);
begin
  value.GetData(PAVInt32(VInfo.PValue)^, SizeOf(Int32));
end;

function TAVValue.Int32GetAsType<T>: T;
var v: TAVValue;
begin
  v.PointTo<T>(Result);
  v.AsInteger := PAVInt32(VInfo.PValue)^;
end;

procedure TAVValue.Int32SetAsType<T>(value: T);
var v: TAVValue;
begin
  v.PointTo<T>(value);
  PAVInt32(VInfo.PValue)^ := v.AsInteger;
end;

function TAVValue.Int32IsEmpty: boolean;
begin
  Result := PAVInt32(VInfo.PValue)^ = 0;
end;

function TAVValue.Int32CompareTo(value: TAVValue): integer;
begin
  Result := PAVInt32(VInfo.PValue)^ - value.AsInteger;
end;

function TAVValue.Int32GetFormatedValue(FormatStr: string): string;
begin
  Result := Trim(Format(FormatStr, [GetAsInteger]));
end;

procedure TAVValue.Int32SetFormatedValue(FormatStr: string; value: string);
begin
  SetAsString(value);
end;

procedure TAVValue.Int32CopyFrom(value: TAVValue);
begin
  Int32SetAsInteger(value.AsInteger);
end;

procedure TAVValue.Int32InitMethods;
begin
  fGetAsString := Int32GetAsString;
  fSetAsString := Int32SetAsString;
  fGetAsInteger := Int32GetAsInteger;
  fSetAsInteger := Int32SetAsInteger;
  fGetAsInt64 := Int32GetAsInt64;
  fSetAsInt64 := Int32SetAsInt64;
  fGetAsDate := Int32GetAsDate;
  fSetAsDate := Int32SetAsDate;
  fGetAsBool := Int32GetAsBool;
  fSetAsBool := Int32SetAsBool;
  fGetAsFloat := Int32GetAsFloat;
  fSetAsFloat := Int32SetAsFloat;
  fGetAsObject := Int32GetAsObject;
  fSetAsObject := Int32SetAsObject;
  fGetAsValue := Int32GetAsValue;
  fSetAsValue := Int32SetAsValue;
  fGetAsVariant := Int32GetAsVariant;
  fSetAsVariant := Int32SetAsVariant;
  fGetAsBitArray := Int32GetAsBitArray;
  fSetAsBitArray := Int32SetAsBitArray;
  fGetFormatedValue := Int32GetFormatedValue;
  fSetFormatedValue := Int32SetFormatedValue;
  fCopyFrom := Int32CopyFrom;
  fIsEmpty := Int32IsEmpty;
  fCompareTo := Int32CompareTo;
end;

//Int64

function TAVValue.Int64GetAsString: string;
begin
  Result := IntToStr(PAVInt64(VInfo.PValue)^);
end;

procedure TAVValue.Int64SetAsString(value: string);
begin
  PAVInt64(VInfo.PValue)^ := StrToIntAnyway(value);
end;

function TAVValue.Int64GetAsInteger: integer;
begin
  Result := PAVInt64(VInfo.PValue)^;
end;

procedure TAVValue.Int64SetAsInteger(value: integer);
begin
  PAVInt64(VInfo.PValue)^ := value;
end;

function TAVValue.Int64GetAsInt64: Int64;
begin
  Result := PAVInt64(VInfo.PValue)^;
end;

procedure TAVValue.Int64SetAsInt64(value: Int64);
begin
  PAVInt64(VInfo.PValue)^ := value;
end;

function TAVValue.Int64GetAsDate: TDateTime;
begin
  Result := PAVInt64(VInfo.PValue)^;
end;

procedure TAVValue.Int64SetAsDate(value: TDateTime);
begin
  PAVInt64(VInfo.PValue)^ := Trunc(value);
end;

function TAVValue.Int64GetAsBool: boolean;
begin
  Result := PAVInt64(VInfo.PValue)^ <> 0;
end;

procedure TAVValue.Int64SetAsBool(value: boolean);
begin
  if value
    then PAVInt64(VInfo.PValue)^ := 1
    else PAVInt64(VInfo.PValue)^ := 0;
end;

function TAVValue.Int64GetAsFloat: double;
begin
  Result := PAVInt64(VInfo.PValue)^;
end;

procedure TAVValue.Int64SetAsFloat(value: double);
begin
  PAVInt64(VInfo.PValue)^ := Trunc(value);
end;

function TAVValue.Int64GetAsObject: TObject;
begin
  Result := Pointer(NativeInt(PAVInt64(VInfo.PValue)^));
end;

procedure TAVValue.Int64SetAsObject(value: TObject);
begin
  PAVInt64(VInfo.PValue)^ := NativeInt(value);
end;

function TAVValue.Int64GetAsValue: TValue;
begin
  Result := TValue.From<Int64>(PAVInt64(VInfo.PValue)^);
end;

procedure TAVValue.Int64SetAsValue(value: TValue);
begin
  PAVInt64(VInfo.PValue)^ := value.AsOrdinal;
end;

function TAVValue.Int64GetAsVariant: Variant;
begin
  Result := PAVInt64(VInfo.PValue)^;
end;

procedure TAVValue.Int64SetAsVariant(value: Variant);
begin
  PAVInt64(VInfo.PValue)^ := value;
end;

function TAVValue.Int64GetAsBitArray: TBitArray;
begin
  Result.SetData(PAVInt64(VInfo.PValue)^, SizeOf(Int64));
end;

procedure TAVValue.Int64SetAsBitArray(value: TBitArray);
begin
  value.GetData(PAVInt64(VInfo.PValue)^, SizeOf(Int64));
end;

function TAVValue.Int64GetAsType<T>: T;
var v: TAVValue;
begin
  v.PointTo<T>(Result);
  v.AsInt64 := PAVInt64(VInfo.PValue)^;
end;

procedure TAVValue.Int64SetAsType<T>(value: T);
var v: TAVValue;
begin
  v.PointTo<T>(value);
  PAVInt64(VInfo.PValue)^ := v.AsInt64;
end;

function TAVValue.Int64IsEmpty: boolean;
begin
  Result := PAVInt64(VInfo.PValue)^ = 0;
end;

function TAVValue.Int64CompareTo(value: TAVValue): integer;
begin
  if PAVInt64(VInfo.PValue)^ < value.AsInt64 then Result := -1 else
  if PAVInt64(VInfo.PValue)^ > value.AsInt64 then Result := 1 else
    Result := 0;
end;

function TAVValue.Int64GetFormatedValue(FormatStr: string): string;
begin
  Result := Trim(Format(FormatStr, [GetAsInt64]));
end;

procedure TAVValue.Int64SetFormatedValue(FormatStr: string; value: string);
begin
  SetAsString(value);
end;

procedure TAVValue.Int64CopyFrom(value: TAVValue);
begin
  Int64SetAsInt64(value.AsInt64);
end;

procedure TAVValue.Int64InitMethods;
begin
  fGetAsString := Int64GetAsString;
  fSetAsString := Int64SetAsString;
  fGetAsInteger := Int64GetAsInteger;
  fSetAsInteger := Int64SetAsInteger;
  fGetAsInt64 := Int64GetAsInt64;
  fSetAsInt64 := Int64SetAsInt64;
  fGetAsDate := Int64GetAsDate;
  fSetAsDate := Int64SetAsDate;
  fGetAsBool := Int64GetAsBool;
  fSetAsBool := Int64SetAsBool;
  fGetAsFloat := Int64GetAsFloat;
  fSetAsFloat := Int64SetAsFloat;
  fGetAsObject := Int64GetAsObject;
  fSetAsObject := Int64SetAsObject;
  fGetAsValue := Int64GetAsValue;
  fSetAsValue := Int64SetAsValue;
  fGetAsVariant := Int64GetAsVariant;
  fSetAsVariant := Int64SetAsVariant;
  fGetAsBitArray := Int64GetAsBitArray;
  fSetAsBitArray := Int64SetAsBitArray;
  fGetFormatedValue := Int64GetFormatedValue;
  fSetFormatedValue := Int64SetFormatedValue;
  fCopyFrom := Int64CopyFrom;
  fIsEmpty := Int64IsEmpty;
  fCompareTo := Int64CompareTo;
end;

//NativeInt

function TAVValue.NativeIntGetAsString: string;
begin
  Result := IntToStr(PAVNativeInt(VInfo.PValue)^);
end;

procedure TAVValue.NativeIntSetAsString(value: string);
begin
  PAVNativeInt(VInfo.PValue)^ := StrToIntAnyway(value);
end;

function TAVValue.NativeIntGetAsInteger: integer;
begin
  Result := PAVNativeInt(VInfo.PValue)^;
end;

procedure TAVValue.NativeIntSetAsInteger(value: integer);
begin
  PAVNativeInt(VInfo.PValue)^ := value;
end;

function TAVValue.NativeIntGetAsInt64: Int64;
begin
  Result := PAVNativeInt(VInfo.PValue)^;
end;

procedure TAVValue.NativeIntSetAsInt64(value: Int64);
begin
  PAVNativeInt(VInfo.PValue)^ := value;
end;

function TAVValue.NativeIntGetAsDate: TDateTime;
begin
  Result := PAVNativeInt(VInfo.PValue)^;
end;

procedure TAVValue.NativeIntSetAsDate(value: TDateTime);
begin
  PAVNativeInt(VInfo.PValue)^ := Trunc(value);
end;

function TAVValue.NativeIntGetAsBool: boolean;
begin
  Result := PAVNativeInt(VInfo.PValue)^ <> 0;
end;

procedure TAVValue.NativeIntSetAsBool(value: boolean);
begin
  if value
    then PAVNativeInt(VInfo.PValue)^ := 1
    else PAVNativeInt(VInfo.PValue)^ := 0;
end;

function TAVValue.NativeIntGetAsFloat: double;
begin
  Result := PAVNativeInt(VInfo.PValue)^;
end;

procedure TAVValue.NativeIntSetAsFloat(value: double);
begin
  PAVNativeInt(VInfo.PValue)^ := Trunc(value);
end;

function TAVValue.NativeIntGetAsObject: TObject;
begin
  Result := Pointer(PAVNativeInt(VInfo.PValue)^);
end;

procedure TAVValue.NativeIntSetAsObject(value: TObject);
begin
  PAVNativeInt(VInfo.PValue)^ := NativeInt(value);
end;

function TAVValue.NativeIntGetAsValue: TValue;
begin
  Result := TValue.From<NativeInt>(PAVNativeInt(VInfo.PValue)^);
end;

procedure TAVValue.NativeIntSetAsValue(value: TValue);
begin
  PAVNativeInt(VInfo.PValue)^ := value.AsOrdinal;
end;

function TAVValue.NativeIntGetAsVariant: Variant;
begin
  Result := PAVNativeInt(VInfo.PValue)^;
end;

procedure TAVValue.NativeIntSetAsVariant(value: Variant);
begin
  PAVNativeInt(VInfo.PValue)^ := value;
end;

function TAVValue.NativeIntGetAsBitArray: TBitArray;
begin
  Result.SetData(PAVNativeInt(VInfo.PValue)^, SizeOf(NativeInt));
end;

procedure TAVValue.NativeIntSetAsBitArray(value: TBitArray);
begin
  value.GetData(PAVNativeInt(VInfo.PValue)^, SizeOf(NativeInt));
end;

function TAVValue.NativeIntGetAsType<T>: T;
var v: TAVValue;
begin
  v.PointTo<T>(Result);
{$IFDEF CPUX64}
  v.AsInt64 := PAVNativeInt(VInfo.PValue)^;
{$ELSE}
  v.AsInteger := PAVNativeInt(VInfo.PValue)^;
{$ENDIF}
end;

procedure TAVValue.NativeIntSetAsType<T>(value: T);
var v: TAVValue;
begin
  v.PointTo<T>(value);
{$IFDEF CPUX64}
  PAVNativeInt(VInfo.PValue)^ := v.AsInt64;
{$ELSE}
  PAVNativeInt(VInfo.PValue)^ := v.AsInteger;
{$ENDIF}
end;

function TAVValue.NativeIntIsEmpty: boolean;
begin
  Result := PAVNativeInt(VInfo.PValue)^ = 0;
end;

function TAVValue.NativeIntCompareTo(value: TAVValue): integer;
begin
  if PAVNativeInt(VInfo.PValue)^ < {$IFDEF CPU64}value.AsInt64{$ELSE}value.AsInteger{$ENDIF} then Result := -1 else
  if PAVNativeInt(VInfo.PValue)^ > {$IFDEF CPU64}value.AsInt64{$ELSE}value.AsInteger{$ENDIF} then Result := 1 else
    Result := 0;
end;

function TAVValue.NativeIntGetFormatedValue(FormatStr: string): string;
begin
  Result := Trim(Format(FormatStr, [GetAsInt64]));
end;

procedure TAVValue.NativeIntSetFormatedValue(FormatStr: string; value: string);
begin
  SetAsString(value);
end;

procedure TAVValue.NativeIntCopyFrom(value: TAVValue);
begin
{$IFDEF CPU64}
  NativeIntSetAsInt64(value.AsInt64);
{$ELSE}
  NativeIntSetAsInteger(value.AsInteger);
{$ENDIF}
end;

procedure TAVValue.NativeIntInitMethods;
begin
  fGetAsString := NativeIntGetAsString;
  fSetAsString := NativeIntSetAsString;
  fGetAsInteger := NativeIntGetAsInteger;
  fSetAsInteger := NativeIntSetAsInteger;
  fGetAsInt64 := NativeIntGetAsInt64;
  fSetAsInt64 := NativeIntSetAsInt64;
  fGetAsDate := NativeIntGetAsDate;
  fSetAsDate := NativeIntSetAsDate;
  fGetAsBool := NativeIntGetAsBool;
  fSetAsBool := NativeIntSetAsBool;
  fGetAsFloat := NativeIntGetAsFloat;
  fSetAsFloat := NativeIntSetAsFloat;
  fGetAsObject := NativeIntGetAsObject;
  fSetAsObject := NativeIntSetAsObject;
  fGetAsValue := NativeIntGetAsValue;
  fSetAsValue := NativeIntSetAsValue;
  fGetAsVariant := NativeIntGetAsVariant;
  fSetAsVariant := NativeIntSetAsVariant;
  fGetAsBitArray := NativeIntGetAsBitArray;
  fSetAsBitArray := NativeIntSetAsBitArray;
  fGetFormatedValue := NativeIntGetFormatedValue;
  fSetFormatedValue := NativeIntSetFormatedValue;
  fCopyFrom := NativeIntCopyFrom;
  fIsEmpty := NativeIntIsEmpty;
  fCompareTo := NativeIntCompareTo;
end;

//Float

function TAVValue.FloatGetAsString: string;
begin
  Result := FloatToStr(PAVDouble(VInfo.PValue)^);
end;

procedure TAVValue.FloatSetAsString(value: string);
begin
  PAVDouble(VInfo.PValue)^ := StrToFloatAnyway(value);
end;

function TAVValue.FloatGetAsInteger: integer;
begin
  Result := Trunc(PAVDouble(VInfo.PValue)^);
end;

procedure TAVValue.FloatSetAsInteger(value: integer);
begin
  PAVDouble(VInfo.PValue)^ := value;
end;

function TAVValue.FloatGetAsInt64: Int64;
begin
  Result := Trunc(PAVDouble(VInfo.PValue)^);
end;

procedure TAVValue.FloatSetAsInt64(value: Int64);
begin
  PAVDouble(VInfo.PValue)^ := value;
end;

function TAVValue.FloatGetAsDate: TDateTime;
begin
  Result := PAVDouble(VInfo.PValue)^;
end;

procedure TAVValue.FloatSetAsDate(value: TDateTime);
begin
  PAVDouble(VInfo.PValue)^ := value;
end;

function TAVValue.FloatGetAsBool: boolean;
begin
  Result := PAVDouble(VInfo.PValue)^ <> 0;
end;

procedure TAVValue.FloatSetAsBool(value: boolean);
begin
  if value
    then PAVDouble(VInfo.PValue)^ := 1
    else PAVDouble(VInfo.PValue)^ := 0;
end;

function TAVValue.FloatGetAsFloat: double;
begin
  Result := PAVDouble(VInfo.PValue)^;
end;

procedure TAVValue.FloatSetAsFloat(value: double);
begin
  PAVDouble(VInfo.PValue)^ := value;
end;

function TAVValue.FloatGetAsObject: TObject;
begin
  Result := nil
end;

procedure TAVValue.FloatSetAsObject(value: TObject);
begin
  PAVDouble(VInfo.PValue)^ := 0;
end;

function TAVValue.FloatGetAsValue: TValue;
begin
  Result := TValue.From<double>(PAVDouble(VInfo.PValue)^);
end;

procedure TAVValue.FloatSetAsValue(value: TValue);
begin
  PAVDouble(VInfo.PValue)^ := value.AsExtended;
end;

function TAVValue.FloatGetAsVariant: Variant;
begin
  Result := PAVDouble(VInfo.PValue)^;
end;

procedure TAVValue.FloatSetAsVariant(value: Variant);
begin
  PAVDouble(VInfo.PValue)^ := value;
end;

function TAVValue.FloatGetAsBitArray: TBitArray;
begin
  Result.SetData(PAVDouble(VInfo.PValue)^, SizeOf(double));
end;

procedure TAVValue.FloatSetAsBitArray(value: TBitArray);
begin
  value.GetData(PAVDouble(VInfo.PValue)^, SizeOf(double));
end;

function TAVValue.FloatGetAsType<T>: T;
var v: TAVValue;
begin
  v.PointTo<T>(Result);
  v.AsFloat := PAVDouble(VInfo.PValue)^;
end;

procedure TAVValue.FloatSetAsType<T>(value: T);
var v: TAVValue;
begin
  v.PointTo<T>(value);
  PAVDouble(VInfo.PValue)^ := v.AsFloat;
end;

function TAVValue.FloatIsEmpty: boolean;
begin
  Result := PAVDouble(VInfo.PValue)^ = 0;
end;

function TAVValue.FloatCompareTo(value: TAVValue): integer;
begin
  if PAVDouble(VInfo.PValue)^ < value.AsFloat then Result := -1 else
  if PAVDouble(VInfo.PValue)^ > value.AsFloat then Result := 1 else
    Result := 0;
end;

function TAVValue.FloatGetFormatedValue(FormatStr: string): string;
begin
  Result := Trim(Format(FormatStr, [GetAsFloat]));
end;

procedure TAVValue.FloatSetFormatedValue(FormatStr: string; value: string);
var d: double;
    fset: TFormatSettings;
begin
  fset := FormatSettings;
  if Pos('n', FormatStr) > 0 then fset.ThousandSeparator := ' ';
  if TryStrToFloat(value, d, fset) then SetAsFloat(d) else SetAsString(value);
end;

procedure TAVValue.FloatCopyFrom(value: TAVValue);
begin
  FloatSetAsFloat(value.AsFloat);
end;

procedure TAVValue.FloatInitMethods;
begin
  fGetAsString := FloatGetAsString;
  fSetAsString := FloatSetAsString;
  fGetAsInteger := FloatGetAsInteger;
  fSetAsInteger := FloatSetAsInteger;
  fGetAsInt64 := FloatGetAsInt64;
  fSetAsInt64 := FloatSetAsInt64;
  fGetAsDate := FloatGetAsDate;
  fSetAsDate := FloatSetAsDate;
  fGetAsBool := FloatGetAsBool;
  fSetAsBool := FloatSetAsBool;
  fGetAsFloat := FloatGetAsFloat;
  fSetAsFloat := FloatSetAsFloat;
  fGetAsObject := FloatGetAsObject;
  fSetAsObject := FloatSetAsObject;
  fGetAsValue := FloatGetAsValue;
  fSetAsValue := FloatSetAsValue;
  fGetAsVariant := FloatGetAsVariant;
  fSetAsVariant := FloatSetAsVariant;
  fGetAsBitArray := FloatGetAsBitArray;
  fSetAsBitArray := FloatSetAsBitArray;
  fGetFormatedValue := FloatGetFormatedValue;
  fSetFormatedValue := FloatSetFormatedValue;
  fCopyFrom := FloatCopyFrom;
  fIsEmpty := FloatIsEmpty;
  fCompareTo := FloatCompareTo;
end;

//Object

function TAVValue.ObjectGetAsString: string;
begin
  if PAVObject(VInfo.PValue)^ <> nil
    then Result := PAVObject(VInfo.PValue)^.ToString
    else Result := '';
end;

procedure TAVValue.ObjectSetAsString(value: string);
begin

end;

function TAVValue.ObjectGetAsInteger: integer;
begin
  Result := NativeInt(PAVObject(VInfo.PValue)^);
end;

procedure TAVValue.ObjectSetAsInteger(value: integer);
begin
{$IFNDEF CPUX64}
  PAVObject(VInfo.PValue)^ := Pointer(value);
{$ENDIF}
end;

function TAVValue.ObjectGetAsInt64: Int64;
begin
  Result := NativeInt(PAVObject(VInfo.PValue)^);
end;

procedure TAVValue.ObjectSetAsInt64(value: Int64);
begin
{$IFDEF CPUX64}
  PAVObject(VInfo.PValue)^ := Pointer(value);
{$ELSE}
  PAVObject(VInfo.PValue)^ := Pointer(Integer(value));
{$ENDIF}
end;

function TAVValue.ObjectGetAsDate: TDateTime;
begin
  Result := 0;
end;

procedure TAVValue.ObjectSetAsDate(value: TDateTime);
begin
end;

function TAVValue.ObjectGetAsBool: boolean;
begin
  Result := PAVObject(VInfo.PValue)^ <> nil;
end;

procedure TAVValue.ObjectSetAsBool(value: boolean);
begin
end;

function TAVValue.ObjectGetAsFloat: double;
begin
  Result := 0;
end;

procedure TAVValue.ObjectSetAsFloat(value: double);
begin
end;

function TAVValue.ObjectGetAsObject: TObject;
begin
  Result := PAVObject(VInfo.PValue)^;
end;

procedure TAVValue.ObjectSetAsObject(value: TObject);
begin
  PAVObject(VInfo.PValue)^ := value;
end;

function TAVValue.ObjectGetAsValue: TValue;
begin
  Result := TValue.From<TObject>(PAVObject(VInfo.PValue)^);
end;

procedure TAVValue.ObjectSetAsValue(value: TValue);
begin
  PAVObject(VInfo.PValue)^ := value.AsObject;
end;

function TAVValue.ObjectGetAsVariant: Variant;
begin
  //todo object to variant
end;

procedure TAVValue.ObjectSetAsVariant(value: Variant);
begin
  //todo variant to object
end;

function TAVValue.ObjectGetAsBitArray: TBitArray;
begin
end;

procedure TAVValue.ObjectSetAsBitArray(value: TBitArray);
begin
end;

function TAVValue.ObjectGetAsType<T>: T;
var v: TAVValue;
begin
  v.PointTo<T>(Result);
  v.AsObject := PAVObject(VInfo.PValue)^;
end;

procedure TAVValue.ObjectSetAsType<T>(value: T);
var v: TAVValue;
begin
  v.PointTo<T>(value);
  PAVObject(VInfo.PValue)^ := v.AsObject;
end;

function TAVValue.ObjectIsEmpty: boolean;
begin
  Result := PAVObject(VInfo.PValue)^ = nil;
end;

function TAVValue.ObjectCompareTo(value: TAVValue): integer;
begin
  if NativeInt(PAVObject(VInfo.PValue)^) < NativeInt(value.AsObject) then Result := -1 else
  if NativeInt(PAVObject(VInfo.PValue)^) > NativeInt(value.AsObject) then Result := 1 else
    Result := 0;
end;

function TAVValue.ObjectGetFormatedValue(FormatStr: string): string;
begin
  Result := GetAsString;
end;

procedure TAVValue.ObjectSetFormatedValue(FormatStr: string; value: string);
begin
  SetAsString(value);
end;

procedure TAVValue.ObjectCopyFrom(value: TAVValue);
begin
  ObjectSetAsObject(value.AsObject);
end;

procedure TAVValue.ObjectInitMethods;
begin
  fGetAsString := ObjectGetAsString;
  fSetAsString := ObjectSetAsString;
  fGetAsInteger := ObjectGetAsInteger;
  fSetAsInteger := ObjectSetAsInteger;
  fGetAsInt64 := ObjectGetAsInt64;
  fSetAsInt64 := ObjectSetAsInt64;
  fGetAsDate := ObjectGetAsDate;
  fSetAsDate := ObjectSetAsDate;
  fGetAsBool := ObjectGetAsBool;
  fSetAsBool := ObjectSetAsBool;
  fGetAsFloat := ObjectGetAsFloat;
  fSetAsFloat := ObjectSetAsFloat;
  fGetAsObject := ObjectGetAsObject;
  fSetAsObject := ObjectSetAsObject;
  fGetAsValue := ObjectGetAsValue;
  fSetAsValue := ObjectSetAsValue;
  fGetAsVariant := ObjectGetAsVariant;
  fSetAsVariant := ObjectSetAsVariant;
  fGetAsBitArray := ObjectGetAsBitArray;
  fSetAsBitArray := ObjectSetAsBitArray;
  fGetFormatedValue := ObjectGetFormatedValue;
  fSetFormatedValue := ObjectSetFormatedValue;
  fCopyFrom := ObjectCopyFrom;
  fIsEmpty := ObjectIsEmpty;
  fCompareTo := ObjectCompareTo;
end;

//Date

function TAVValue.DateGetAsString: string;
begin
  Result := DateToStr(PAVDate(VInfo.PValue)^);
end;

procedure TAVValue.DateSetAsString(value: string);
begin
  PAVDate(VInfo.PValue)^ := StrToDateTimeAnyway(value);
end;

function TAVValue.DateGetAsInteger: integer;
begin
  Result := Trunc(PAVDate(VInfo.PValue)^);
end;

procedure TAVValue.DateSetAsInteger(value: integer);
begin
  PAVDate(VInfo.PValue)^ := value;
end;

function TAVValue.DateGetAsInt64: Int64;
begin
  Result := Trunc(PAVDate(VInfo.PValue)^);
end;

procedure TAVValue.DateSetAsInt64(value: Int64);
begin
  PAVDate(VInfo.PValue)^ := value;
end;

function TAVValue.DateGetAsDate: TDateTime;
begin
  Result := PAVDate(VInfo.PValue)^;
end;

procedure TAVValue.DateSetAsDate(value: TDateTime);
begin
  PAVDate(VInfo.PValue)^ := value;
end;

function TAVValue.DateGetAsBool: boolean;
begin
  Result := PAVDate(VInfo.PValue)^ > 0;
end;

procedure TAVValue.DateSetAsBool(value: boolean);
begin
  if value
    then PAVDate(VInfo.PValue)^ := Now
    else PAVDate(VInfo.PValue)^ := 0;
end;

function TAVValue.DateGetAsFloat: double;
begin
  Result := PAVDate(VInfo.PValue)^;
end;

procedure TAVValue.DateSetAsFloat(value: double);
begin
  PAVDate(VInfo.PValue)^ := value;
end;

function TAVValue.DateGetAsObject: TObject;
begin
  Result := nil
end;

procedure TAVValue.DateSetAsObject(value: TObject);
begin
  PAVDate(VInfo.PValue)^ := 0;
end;

function TAVValue.DateGetAsValue: TValue;
begin
  Result := TValue.From<TDateTime>(PAVDate(VInfo.PValue)^);
end;

procedure TAVValue.DateSetAsValue(value: TValue);
begin
  PAVDate(VInfo.PValue)^ := value.AsExtended;
end;

function TAVValue.DateGetAsVariant: Variant;
begin
  Result := PAVDate(VInfo.PValue)^;
end;

procedure TAVValue.DateSetAsVariant(value: Variant);
begin
  PAVDate(VInfo.PValue)^ := value;
end;

function TAVValue.DateGetAsBitArray: TBitArray;
begin
  Result.SetData(PAVDate(VInfo.PValue)^, SizeOf(TDateTime));
end;

procedure TAVValue.DateSetAsBitArray(value: TBitArray);
begin
  value.GetData(PAVDate(VInfo.PValue)^, SizeOf(TDateTime));
end;

function TAVValue.DateGetAsType<T>: T;
var v: TAVValue;
begin
  v.PointTo<T>(Result);
  v.AsDate := PAVDate(VInfo.PValue)^;
end;

procedure TAVValue.DateSetAsType<T>(value: T);
var v: TAVValue;
begin
  v.PointTo<T>(value);
  PAVDate(VInfo.PValue)^ := v.AsDate;
end;

function TAVValue.DateIsEmpty: boolean;
begin
  Result := PAVDate(VInfo.PValue)^ = 0;
end;

function TAVValue.DateCompareTo(value: TAVValue): integer;
begin
  if PAVDate(VInfo.PValue)^ < value.AsDate then Result := -1 else
  if PAVDate(VInfo.PValue)^ > value.AsDate then Result := 1 else
    Result := 0;
end;

function TAVValue.DateGetFormatedValue(FormatStr: string): string;
begin
  Result := FormatDateTime(FormatStr, GetAsDate);
end;

procedure TAVValue.DateSetFormatedValue(FormatStr: string; value: string);
begin
  SetAsDate(StrToDateTimeAnyway(value, FormatStr));
end;

procedure TAVValue.DateCopyFrom(value: TAVValue);
begin
  DateSetAsDate(value.AsDate);
end;

procedure TAVValue.DateInitMethods;
begin
  fGetAsString := DateGetAsString;
  fSetAsString := DateSetAsString;
  fGetAsInteger := DateGetAsInteger;
  fSetAsInteger := DateSetAsInteger;
  fGetAsInt64 := DateGetAsInt64;
  fSetAsInt64 := DateSetAsInt64;
  fGetAsDate := DateGetAsDate;
  fSetAsDate := DateSetAsDate;
  fGetAsBool := DateGetAsBool;
  fSetAsBool := DateSetAsBool;
  fGetAsFloat := DateGetAsFloat;
  fSetAsFloat := DateSetAsFloat;
  fGetAsObject := DateGetAsObject;
  fSetAsObject := DateSetAsObject;
  fGetAsValue := DateGetAsValue;
  fSetAsValue := DateSetAsValue;
  fGetAsVariant := DateGetAsVariant;
  fSetAsVariant := DateSetAsVariant;
  fGetAsBitArray := DateGetAsBitArray;
  fSetAsBitArray := DateSetAsBitArray;
  fGetFormatedValue := DateGetFormatedValue;
  fSetFormatedValue := DateSetFormatedValue;
  fCopyFrom := DateCopyFrom;
  fIsEmpty := DateIsEmpty;
  fCompareTo := DateCompareTo;
end;

//Bool

function TAVValue.BoolGetAsString: string;
begin
  Result := AVUtils.BoolToStr(PAVBool(VInfo.PValue)^);
end;

procedure TAVValue.BoolSetAsString(value: string);
begin
  PAVBool(VInfo.PValue)^ := StrToBoolAnyway(value);
end;

function TAVValue.BoolGetAsInteger: integer;
begin
  if PAVBool(VInfo.PValue)^ then Result := 1 else Result := 0;
end;

procedure TAVValue.BoolSetAsInteger(value: integer);
begin
  PAVBool(VInfo.PValue)^ := value <> 0;
end;

function TAVValue.BoolGetAsInt64: Int64;
begin
  if PAVBool(VInfo.PValue)^ then Result := 1 else Result := 0;
end;

procedure TAVValue.BoolSetAsInt64(value: Int64);
begin
  PAVBool(VInfo.PValue)^ := value <> 0;
end;

function TAVValue.BoolGetAsDate: TDateTime;
begin
  if PAVBool(VInfo.PValue)^ then Result := Now else Result := 0;
end;

procedure TAVValue.BoolSetAsDate(value: TDateTime);
begin
  PAVBool(VInfo.PValue)^ := value <> 0;
end;

function TAVValue.BoolGetAsBool: boolean;
begin
  Result := PAVBool(VInfo.PValue)^;
end;

procedure TAVValue.BoolSetAsBool(value: boolean);
begin
  PAVBool(VInfo.PValue)^ := value;
end;

function TAVValue.BoolGetAsFloat: double;
begin
  if PAVBool(VInfo.PValue)^ then Result := 1 else Result := 0;
end;

procedure TAVValue.BoolSetAsFloat(value: double);
begin
  PAVBool(VInfo.PValue)^ := value <> 0;
end;

function TAVValue.BoolGetAsObject: TObject;
begin
  Result := nil;
end;

procedure TAVValue.BoolSetAsObject(value: TObject);
begin
  PAVBool(VInfo.PValue)^ := value <> nil;
end;

function TAVValue.BoolGetAsValue: TValue;
begin
  Result := TValue.From<boolean>(PAVBool(VInfo.PValue)^);
end;

procedure TAVValue.BoolSetAsValue(value: TValue);
begin
  PAVBool(VInfo.PValue)^ := value.AsBoolean;
end;

function TAVValue.BoolGetAsVariant: Variant;
begin
  Result := PAVBool(VInfo.PValue)^;
end;

procedure TAVValue.BoolSetAsVariant(value: Variant);
begin
  PAVBool(VInfo.PValue)^ := value;
end;

function TAVValue.BoolGetAsBitArray: TBitArray;
begin
  Result.SetData(PAVBool(VInfo.PValue)^, SizeOf(boolean));
end;

procedure TAVValue.BoolSetAsBitArray(value: TBitArray);
begin
  value.GetData(PAVBool(VInfo.PValue)^, SizeOf(boolean));
end;

function TAVValue.BoolGetAsType<T>: T;
var v: TAVValue;
begin
  v.PointTo<T>(Result);
  v.AsBool := PAVBool(VInfo.PValue)^;
end;

procedure TAVValue.BoolSetAsType<T>(value: T);
var v: TAVValue;
begin
  v.PointTo<T>(value);
  PAVBool(VInfo.PValue)^ := v.AsBool;
end;

function TAVValue.BoolIsEmpty: boolean;
begin
  Result := not PAVBool(VInfo.PValue)^;
end;

function TAVValue.BoolCompareTo(value: TAVValue): integer;
begin
  if PAVBool(VInfo.PValue)^ xor value.AsBool then
  begin
    if not PAVBool(VInfo.PValue)^ then Result := -1 else Result := 1;
  end else Result := 0;
end;

function TAVValue.BoolGetFormatedValue(FormatStr: string): string;
begin
  Result := GetAsString;
end;

procedure TAVValue.BoolSetFormatedValue(FormatStr: string; value: string);
begin
  SetAsString(value);
end;

procedure TAVValue.BoolCopyFrom(value: TAVValue);
begin
  BoolSetAsBool(value.AsBool);
end;

procedure TAVValue.BoolInitMethods;
begin
  fGetAsString := BoolGetAsString;
  fSetAsString := BoolSetAsString;
  fGetAsInteger := BoolGetAsInteger;
  fSetAsInteger := BoolSetAsInteger;
  fGetAsInt64 := BoolGetAsInt64;
  fSetAsInt64 := BoolSetAsInt64;
  fGetAsDate := BoolGetAsDate;
  fSetAsDate := BoolSetAsDate;
  fGetAsBool := BoolGetAsBool;
  fSetAsBool := BoolSetAsBool;
  fGetAsFloat := BoolGetAsFloat;
  fSetAsFloat := BoolSetAsFloat;
  fGetAsObject := BoolGetAsObject;
  fSetAsObject := BoolSetAsObject;
  fGetAsValue := BoolGetAsValue;
  fSetAsValue := BoolSetAsValue;
  fGetAsVariant := BoolGetAsVariant;
  fSetAsVariant := BoolSetAsVariant;
  fGetAsBitArray := BoolGetAsBitArray;
  fSetAsBitArray := BoolSetAsBitArray;
  fGetFormatedValue := BoolGetFormatedValue;
  fSetFormatedValue := BoolSetFormatedValue;
  fCopyFrom := BoolCopyFrom;
  fIsEmpty := BoolIsEmpty;
  fCompareTo := BoolCompareTo;
end;

//TValue

function TAVValue.ValueGetAsString: string;
begin
  if PAVValue(VInfo.PValue)^.TypeInfo = nil then Exit('');

  case PAVValue(VInfo.PValue)^.TypeInfo^.Kind of
    tkChar, tkString, tkWChar, tkLString, tkWString, tkUString:
      Result := PAVValue(VInfo.PValue)^.AsString;
    tkInteger, tkInt64:
      Result := IntToStr(PAVValue(VInfo.PValue)^.AsOrdinal);
    tkFloat:
      Result := FloatToStr(PAVValue(VInfo.PValue)^.AsExtended);
  else
    begin
      try
        Result := PAVValue(VInfo.PValue)^.AsString;
      except
        Result := '';
      end;
    end;
  end;
end;

procedure TAVValue.ValueSetAsString(value: string);
begin
  PAVValue(VInfo.PValue)^ := TValue.From<string>(value);
end;

function TAVValue.ValueGetAsInteger: integer;
begin
  Result := PAVValue(VInfo.PValue)^.AsOrdinal;
end;

procedure TAVValue.ValueSetAsInteger(value: integer);
begin
  PAVValue(VInfo.PValue)^ := TValue.From<integer>(value);
end;

function TAVValue.ValueGetAsInt64: Int64;
begin
  Result := PAVValue(VInfo.PValue)^.AsOrdinal;
end;

procedure TAVValue.ValueSetAsInt64(value: Int64);
begin
  PAVValue(VInfo.PValue)^ := TValue.From<Int64>(value);
end;

function TAVValue.ValueGetAsDate: TDateTime;
begin
  Result := PAVValue(VInfo.PValue)^.AsType<TDateTime>;
end;

procedure TAVValue.ValueSetAsDate(value: TDateTime);
begin
  PAVValue(VInfo.PValue)^ := TValue.From<TDateTime>(value);
end;

function TAVValue.ValueGetAsBool: boolean;
begin
  Result := PAVValue(VInfo.PValue)^.AsBoolean;
end;

procedure TAVValue.ValueSetAsBool(value: boolean);
begin
  PAVValue(VInfo.PValue)^ := TValue.From<boolean>(value);
end;

function TAVValue.ValueGetAsFloat: double;
begin
  Result := PAVValue(VInfo.PValue)^.AsExtended;
end;

procedure TAVValue.ValueSetAsFloat(value: double);
begin
  PAVValue(VInfo.PValue)^ := TValue.From<double>(value);
end;

function TAVValue.ValueGetAsObject: TObject;
begin
  Result := PAVValue(VInfo.PValue)^.AsObject;
end;

procedure TAVValue.ValueSetAsObject(value: TObject);
begin
  PAVValue(VInfo.PValue)^ := TValue.From<TObject>(value);
end;

function TAVValue.ValueGetAsValue: TValue;
begin
  Result := PAVValue(VInfo.PValue)^;
end;

procedure TAVValue.ValueSetAsValue(value: TValue);
begin
  PAVValue(VInfo.PValue)^ := value;
end;

function TAVValue.ValueGetAsVariant: Variant;
begin
  Result := PAVValue(VInfo.PValue)^.AsVariant;
end;

procedure TAVValue.ValueSetAsVariant(value: Variant);
begin
  PAVValue(VInfo.PValue)^ := TValue.FromVariant(value);
end;

function TAVValue.ValueGetAsBitArray: TBitArray;
begin
  Result := PAVValue(VInfo.PValue)^.AsType<TBitArray>;
end;

procedure TAVValue.ValueSetAsBitArray(value: TBitArray);
begin
  PAVValue(VInfo.PValue)^ := TValue.From<TBitArray>(value);
end;

function TAVValue.ValueGetAsType<T>: T;
begin
  Result := PAVValue(VInfo.PValue)^.AsType<T>;
end;

procedure TAVValue.ValueSetAsType<T>(value: T);
begin
  PAVValue(VInfo.PValue)^ := TValue.From<T>(value);
end;

function TAVValue.ValueIsEmpty: boolean;
begin
  Result := PAVValue(VInfo.PValue)^.IsEmpty;
end;

function TAVValue.ValueCompareTo(value: TAVValue): integer;
var avType: TAVType;
begin
  if TryAVTypeFromTypeInfo(VInfo.ValueInfo, avType) then begin
    case avType of
      avtString,
      avtBitArray,
      avtRecord:
        Result := CompareText(GetAsString, value.AsString);
      avtByte,
      avtInt16,
      avtInt32:
        Result := GetAsInteger - value.AsInteger;
      avtInt64,
      avtNativeInt:
        Result := GetAsInt64 - value.AsInt64;
      avtDouble,
      avtDate:
        if GetAsFloat < value.AsFloat then Result := -1 else
        if GetAsFloat > value.AsFloat then Result := 1 else Result := 0;
      avtObject:
        if NativeInt(GetAsObject) < NativeInt(value.AsObject) then Result := -1 else
        if NativeInt(GetAsObject) > NativeInt(value.AsObject) then Result := 1 else Result := 0;
      avtBool:
        if GetAsBool xor value.AsBool then begin
          if not GetAsBool then Result := -1 else Result := 1;
        end else Result := 0;
      avtVariant:
        if GetAsVariant < value.AsVariant then Result := -1 else
        if GetAsVariant > value.AsVariant then Result := 1 else Result := 0;
      else
        Result := 0;
    end;
  end else Result := 0;
end;

function TAVValue.ValueGetFormatedValue(FormatStr: string): string;
begin
  Result := GetAsString;
end;

procedure TAVValue.ValueSetFormatedValue(FormatStr: string; value: string);
begin
  SetAsString(value);
end;

procedure TAVValue.ValueCopyFrom(value: TAVValue);
begin
  ValueSetAsValue(value.AsValue);
end;

procedure TAVValue.ValueInitMethods;
begin
  fGetAsString := ValueGetAsString;
  fSetAsString := ValueSetAsString;
  fGetAsInteger := ValueGetAsInteger;
  fSetAsInteger := ValueSetAsInteger;
  fGetAsInt64 := ValueGetAsInt64;
  fSetAsInt64 := ValueSetAsInt64;
  fGetAsDate := ValueGetAsDate;
  fSetAsDate := ValueSetAsDate;
  fGetAsBool := ValueGetAsBool;
  fSetAsBool := ValueSetAsBool;
  fGetAsFloat := ValueGetAsFloat;
  fSetAsFloat := ValueSetAsFloat;
  fGetAsObject := ValueGetAsObject;
  fSetAsObject := ValueSetAsObject;
  fGetAsValue := ValueGetAsValue;
  fSetAsValue := ValueSetAsValue;
  fGetAsVariant := ValueGetAsVariant;
  fSetAsVariant := ValueSetAsVariant;
  fGetAsBitArray := ValueGetAsBitArray;
  fSetAsBitArray := ValueSetAsBitArray;
  fGetFormatedValue := ValueGetFormatedValue;
  fSetFormatedValue := ValueSetFormatedValue;
  fCopyFrom := ValueCopyFrom;
  fIsEmpty := ValueIsEmpty;
  fCompareTo := ValueCompareTo;
end;

//Variant

function TAVValue.VariantGetAsString: string;
begin
  case TVarData(PAVVariant(VInfo.PValue)^).VType of
    varOleStr, varStrArg, varString:
      Result := PAVVariant(VInfo.PValue)^;
    varSmallint, varInteger, varShortInt, varByte, varWord, varLongWord,
      varInt64:
      Result := IntToStr(PAVVariant(VInfo.PValue)^);
    varSingle, varDouble, varCurrency:
      Result := FloatToStr(PAVVariant(VInfo.PValue)^);
    varDate:
      Result := DateTimeToStr(PAVVariant(VInfo.PValue)^);
    varBoolean:
      Result := AVUtils.BoolToStr(PAVVariant(VInfo.PValue)^);
  else
    begin
      try
        Result := PAVVariant(VInfo.PValue)^;
      except
        Result := '';
      end;
    end;
  end;
end;

procedure TAVValue.VariantSetAsString(value: string);
begin
  PAVVariant(VInfo.PValue)^ := value;
end;

function TAVValue.VariantGetAsInteger: integer;
begin
  Result := PAVVariant(VInfo.PValue)^;
end;

procedure TAVValue.VariantSetAsInteger(value: integer);
begin
  PAVVariant(VInfo.PValue)^ := value;
end;

function TAVValue.VariantGetAsInt64: Int64;
begin
  Result := PAVVariant(VInfo.PValue)^;
end;

procedure TAVValue.VariantSetAsInt64(value: Int64);
begin
  PAVVariant(VInfo.PValue)^ := value;
end;

function TAVValue.VariantGetAsDate: TDateTime;
begin
  Result := PAVVariant(VInfo.PValue)^;
end;

procedure TAVValue.VariantSetAsDate(value: TDateTime);
begin
  PAVVariant(VInfo.PValue)^ := value;
end;

function TAVValue.VariantGetAsBool: boolean;
begin
  Result := PAVVariant(VInfo.PValue)^;
end;

procedure TAVValue.VariantSetAsBool(value: boolean);
begin
  PAVVariant(VInfo.PValue)^ := value;
end;

function TAVValue.VariantGetAsFloat: double;
begin
  Result := PAVVariant(VInfo.PValue)^;
end;

procedure TAVValue.VariantSetAsFloat(value: double);
begin
  PAVVariant(VInfo.PValue)^ := value;
end;

function TAVValue.VariantGetAsObject: TObject;
begin
  Result := nil;
  //todo variant to object
end;

procedure TAVValue.VariantSetAsObject(value: TObject);
begin
  //todo object to variant
end;

function TAVValue.VariantGetAsValue: TValue;
begin
  Result := TValue.FromVariant(PAVVariant(VInfo.PValue)^);
end;

procedure TAVValue.VariantSetAsValue(value: TValue);
begin
  PAVVariant(VInfo.PValue)^ := value.AsVariant;
end;

function TAVValue.VariantGetAsVariant: Variant;
begin
  Result := PAVVariant(VInfo.PValue)^;
end;

procedure TAVValue.VariantSetAsVariant(value: Variant);
begin
  PAVVariant(VInfo.PValue)^ := value;
end;

function TAVValue.VariantGetAsBitArray: TBitArray;
begin
  // todo
end;

procedure TAVValue.VariantSetAsBitArray(value: TBitArray);
begin
  // todo
end;

function TAVValue.VariantGetAsType<T>: T;
var v: TAVValue;
begin
  v.PointTo<T>(Result);
  v.AsVariant := PAVVariant(VInfo.PValue)^;
end;

procedure TAVValue.VariantSetAsType<T>(value: T);
var v: TAVValue;
begin
  v.PointTo<T>(value);
  PAVVariant(VInfo.PValue)^ := v.AsVariant;
end;

function TAVValue.VariantIsEmpty: boolean;
begin
  Result := PAVVariant(VInfo.PValue)^ = Unassigned;
end;

function TAVValue.VariantCompareTo(value: TAVValue): integer;
begin
  if PAVVariant(VInfo.PValue)^ < value.AsVariant then Result := -1 else
  if PAVVariant(VInfo.PValue)^ > value.AsVariant then Result := 1 else Result := 0;
end;

function TAVValue.VariantGetFormatedValue(FormatStr: string): string;
begin
  Result := GetAsString;
end;

procedure TAVValue.VariantSetFormatedValue(FormatStr: string; value: string);
begin
  SetAsString(value);
end;

procedure TAVValue.VariantCopyFrom(value: TAVValue);
begin
  VariantSetAsVariant(value.AsVariant);
end;

procedure TAVValue.VariantInitMethods;
begin
  fGetAsString := VariantGetAsString;
  fSetAsString := VariantSetAsString;
  fGetAsInteger := VariantGetAsInteger;
  fSetAsInteger := VariantSetAsInteger;
  fGetAsInt64 := VariantGetAsInt64;
  fSetAsInt64 := VariantSetAsInt64;
  fGetAsDate := VariantGetAsDate;
  fSetAsDate := VariantSetAsDate;
  fGetAsBool := VariantGetAsBool;
  fSetAsBool := VariantSetAsBool;
  fGetAsFloat := VariantGetAsFloat;
  fSetAsFloat := VariantSetAsFloat;
  fGetAsObject := VariantGetAsObject;
  fSetAsObject := VariantSetAsObject;
  fGetAsValue := VariantGetAsValue;
  fSetAsValue := VariantSetAsValue;
  fGetAsVariant := VariantGetAsVariant;
  fSetAsVariant := VariantSetAsVariant;
  fGetAsBitArray := VariantGetAsBitArray;
  fSetAsBitArray := VariantSetAsBitArray;
  fGetFormatedValue := VariantGetFormatedValue;
  fSetFormatedValue := VariantSetFormatedValue;
  fCopyFrom := VariantCopyFrom;
  fIsEmpty := VariantIsEmpty;
  fCompareTo := VariantCompareTo;
end;

//BitArray

function TAVValue.BitArrayGetAsString: string;
begin
  Result := PAVBitArray(VInfo.PValue)^.AsString;
end;

procedure TAVValue.BitArraySetAsString(value: string);
begin
  PAVBitArray(VInfo.PValue)^.AsString := value;
end;

function TAVValue.BitArrayGetAsInteger: integer;
begin
  PAVBitArray(VInfo.PValue)^.GetData(Result, SizeOf(Integer));
end;

procedure TAVValue.BitArraySetAsInteger(value: integer);
begin
  PAVBitArray(VInfo.PValue)^.SetData(value, SizeOf(integer));
end;

function TAVValue.BitArrayGetAsInt64: Int64;
begin
  PAVBitArray(VInfo.PValue)^.GetData(Result, SizeOf(Int64));
end;

procedure TAVValue.BitArraySetAsInt64(value: Int64);
begin
  PAVBitArray(VInfo.PValue)^.SetData(value, SizeOf(Int64));
end;

function TAVValue.BitArrayGetAsDate: TDateTime;
begin
  PAVBitArray(VInfo.PValue)^.GetData(Result, SizeOf(TDateTime));
end;

procedure TAVValue.BitArraySetAsDate(value: TDateTime);
begin
  PAVBitArray(VInfo.PValue)^.SetData(value, SizeOf(TDateTime));
end;

function TAVValue.BitArrayGetAsBool: boolean;
begin
  PAVBitArray(VInfo.PValue)^.GetData(Result, SizeOf(boolean));
end;

procedure TAVValue.BitArraySetAsBool(value: boolean);
begin
  PAVBitArray(VInfo.PValue)^.SetData(value, SizeOf(boolean));
end;

function TAVValue.BitArrayGetAsFloat: double;
begin
  PAVBitArray(VInfo.PValue)^.GetData(Result, SizeOf(double));
end;

procedure TAVValue.BitArraySetAsFloat(value: double);
begin
  PAVBitArray(VInfo.PValue)^.SetData(value, SizeOf(double));
end;

function TAVValue.BitArrayGetAsObject: TObject;
begin
  Result := nil
end;

procedure TAVValue.BitArraySetAsObject(value: TObject);
begin
end;

function TAVValue.BitArrayGetAsValue: TValue;
begin
end;

procedure TAVValue.BitArraySetAsValue(value: TValue);
begin
end;

function TAVValue.BitArrayGetAsVariant: Variant;
begin
end;

procedure TAVValue.BitArraySetAsVariant(value: Variant);
begin
end;

function TAVValue.BitArrayGetAsBitArray: TBitArray;
begin
  Result := PAVBitArray(VInfo.PValue)^;
end;

procedure TAVValue.BitArraySetAsBitArray(value: TBitArray);
begin
  PAVBitArray(VInfo.PValue)^ := value;
end;

function TAVValue.BitArrayGetAsType<T>: T;
begin
end;

procedure TAVValue.BitArraySetAsType<T>(value: T);
begin
end;

function TAVValue.BitArrayIsEmpty: boolean;
begin
  Result := PAVBitArray(VInfo.PValue)^.Count = 0;
end;

function TAVValue.BitArrayCompareTo(value: TAVValue): integer;
begin
  Result := CompareText(GetAsString, value.AsString);
end;

function TAVValue.BitArrayGetFormatedValue(FormatStr: string): string;
begin
  Result := GetAsString;
end;

procedure TAVValue.BitArraySetFormatedValue(FormatStr: string; value: string);
begin
  SetAsString(value);
end;

procedure TAVValue.BitArrayCopyFrom(value: TAVValue);
begin
  BitArraySetAsBitArray(value.AsBitArray);
end;

procedure TAVValue.BitArrayInitMethods;
begin
  fGetAsString := BitArrayGetAsString;
  fSetAsString := BitArraySetAsString;
  fGetAsInteger := BitArrayGetAsInteger;
  fSetAsInteger := BitArraySetAsInteger;
  fGetAsInt64 := BitArrayGetAsInt64;
  fSetAsInt64 := BitArraySetAsInt64;
  fGetAsDate := BitArrayGetAsDate;
  fSetAsDate := BitArraySetAsDate;
  fGetAsBool := BitArrayGetAsBool;
  fSetAsBool := BitArraySetAsBool;
  fGetAsFloat := BitArrayGetAsFloat;
  fSetAsFloat := BitArraySetAsFloat;
  fGetAsObject := BitArrayGetAsObject;
  fSetAsObject := BitArraySetAsObject;
  fGetAsValue := BitArrayGetAsValue;
  fSetAsValue := BitArraySetAsValue;
  fGetAsVariant := BitArrayGetAsVariant;
  fSetAsVariant := BitArraySetAsVariant;
  fGetAsBitArray := BitArrayGetAsBitArray;
  fSetAsBitArray := BitArraySetAsBitArray;
  fGetFormatedValue := BitArrayGetFormatedValue;
  fSetFormatedValue := BitArraySetFormatedValue;
  fCopyFrom := BitArrayCopyFrom;
  fIsEmpty := BitArrayIsEmpty;
  fCompareTo := BitArrayCompareTo;
end;

//Record

function TAVValue.RecordGetAsString: string;
var rtti: TAVRttiObj;
    i: integer;
    s: string;
    v: TAVValue;
    val: TValue;
begin
  rtti := TAVValue(Self).GetAsRtti;
  s := '';
  for i := Low(rtti.Fields) to High(rtti.Fields) do begin
    if s <> '' then s := s + #13#10;
    val := rtti[rtti.Fields[i].Name];
    v.PointTo<TValue>(val);
    s := s + rtti.Fields[i].Name + '=' + v.AsString;
  end;

  Result := s;
  //todo: optimize
end;

procedure TAVValue.RecordSetAsString(value: string);
begin
  //todo
end;

function TAVValue.RecordGetAsInteger: integer;
begin
  Result := 0;
  //todo
end;

procedure TAVValue.RecordSetAsInteger(value: integer);
begin
  //todo
end;

function TAVValue.RecordGetAsInt64: Int64;
begin
  Result := 0;
  //todo
end;

procedure TAVValue.RecordSetAsInt64(value: Int64);
begin
  //todo
end;

function TAVValue.RecordGetAsDate: TDateTime;
begin
  Result := 0;
  //todo
end;

procedure TAVValue.RecordSetAsDate(value: TDateTime);
begin
  //todo
end;

function TAVValue.RecordGetAsBool: boolean;
begin
  Result := false;
  //todo
end;

procedure TAVValue.RecordSetAsBool(value: boolean);
begin
  //todo
end;

function TAVValue.RecordGetAsFloat: double;
begin
  Result := 0;
  //todo
end;

procedure TAVValue.RecordSetAsFloat(value: double);
begin
  //todo
end;

function TAVValue.RecordGetAsObject: TObject;
begin
  Result := nil;
  //todo
end;

procedure TAVValue.RecordSetAsObject(value: TObject);
begin
  //todo
end;

function TAVValue.RecordGetAsValue: TValue;
begin
  //todo
end;

procedure TAVValue.RecordSetAsValue(value: TValue);
begin
  //todo
end;

function TAVValue.RecordGetAsVariant: Variant;
begin
  Result := Unassigned;
  //todo
end;

procedure TAVValue.RecordSetAsVariant(value: Variant);
begin
  //todo
end;

function TAVValue.RecordGetAsBitArray: TBitArray;
begin
  //todo
end;

procedure TAVValue.RecordSetAsBitArray(value: TBitArray);
begin
  //todo
end;

function TAVValue.RecordGetAsType<T>: T;
begin
  if VInfo.ValueInfo = System.TypeInfo(T)
    then Result := T(VInfo.PValue^)
    else Result := Default(T);
end;

procedure TAVValue.RecordSetAsType<T>(value: T);
begin
  if VInfo.ValueInfo = System.TypeInfo(T) then begin
    if IsManaged(VInfo.ValueInfo) then
      System.CopyArray(VInfo.PValue, @value, VInfo.ValueInfo, 1)
    else
      System.Move(value, VInfo.PValue^, SizeOf(T));
  end;
end;

function TAVValue.RecordIsEmpty: boolean;
begin
  Result := false;
  //todo
end;

function TAVValue.RecordCompareTo(value: TAVValue): integer;
begin
  Result := CompareText(GetAsString, value.AsString);
end;

function TAVValue.RecordGetFormatedValue(FormatStr: string): string;
begin
  Result := GetAsString;
end;

procedure TAVValue.RecordSetFormatedValue(FormatStr: string; value: string);
begin
  SetAsString(value);
end;

procedure TAVValue.RecordCopyFrom(value: TAVValue);
begin
  //todo
end;

procedure TAVValue.RecordInitMethods;
begin
  fGetAsString := RecordGetAsString;
  fSetAsString := RecordSetAsString;
  fGetAsInteger := RecordGetAsInteger;
  fSetAsInteger := RecordSetAsInteger;
  fGetAsInt64 := RecordGetAsInt64;
  fSetAsInt64 := RecordSetAsInt64;
  fGetAsDate := RecordGetAsDate;
  fSetAsDate := RecordSetAsDate;
  fGetAsBool := RecordGetAsBool;
  fSetAsBool := RecordSetAsBool;
  fGetAsFloat := RecordGetAsFloat;
  fSetAsFloat := RecordSetAsFloat;
  fGetAsObject := RecordGetAsObject;
  fSetAsObject := RecordSetAsObject;
  fGetAsValue := RecordGetAsValue;
  fSetAsValue := RecordSetAsValue;
  fGetAsVariant := RecordGetAsVariant;
  fSetAsVariant := RecordSetAsVariant;
  fGetAsBitArray := RecordGetAsBitArray;
  fSetAsBitArray := RecordSetAsBitArray;
  fGetFormatedValue := RecordGetFormatedValue;
  fSetFormatedValue := RecordSetFormatedValue;
  fCopyFrom := RecordCopyFrom;
  fIsEmpty := RecordIsEmpty;
  fCompareTo := RecordCompareTo;
end;

{$ENDREGION}

// TAVValue

function TAVValue.GetValueType: TAVType;
begin
  Result := VInfo.ValueType;
end;

function TAVValue.GetAsString: string;
begin
  if VInfo.PValue = nil then Exit('');
  Result := fGetAsString;
end;

procedure TAVValue.SetAsString(value: string);
begin
  if VInfo.PValue = nil then Exit;
  fSetAsString(value);
end;

function TAVValue.GetAsInteger: integer;
begin
  if VInfo.PValue = nil then Exit(0);
  Result := fGetAsInteger;
end;

procedure TAVValue.SetAsInteger(value: integer);
begin
  if VInfo.PValue = nil then Exit;
  fSetAsInteger(value);
end;

function TAVValue.GetAsInt64: Int64;
begin
  if VInfo.PValue = nil then Exit(0);
  Result := fGetAsInt64;
end;

procedure TAVValue.SetAsInt64(value: Int64);
begin
  if VInfo.PValue = nil then Exit;
  fSetAsInt64(value);
end;

function TAVValue.GetAsDate: TDateTime;
begin
  if VInfo.PValue = nil then Exit(0);
  Result := fGetAsDate;
end;

procedure TAVValue.SetAsDate(value: TDateTime);
begin
  if VInfo.PValue = nil then Exit;
  fSetAsDate(value);
end;

function TAVValue.GetAsBool: boolean;
begin
  if VInfo.PValue = nil then Exit(false);
  Result := fGetAsBool;
end;

procedure TAVValue.SetAsBool(value: boolean);
begin
  if VInfo.PValue = nil then Exit;
  fSetAsBool(value);
end;

function TAVValue.GetAsFloat: double;
begin
  if VInfo.PValue = nil then Exit(0);
  Result := fGetAsFloat;
end;

procedure TAVValue.SetAsFloat(value: double);
begin
  if VInfo.PValue = nil then Exit;
  fSetAsFloat(value);
end;

function TAVValue.GetAsObject: TObject;
begin
  if VInfo.PValue = nil then Exit(nil);
  Result := fGetAsObject;
end;

procedure TAVValue.SetAsObject(value: TObject);
begin
  if VInfo.PValue = nil then Exit;
  fSetAsObject(value);
end;

function TAVValue.GetAsValue: TValue;
begin
  if VInfo.PValue = nil then Exit;
  Result := fGetAsValue;
end;

procedure TAVValue.SetAsValue(value: TValue);
begin
  if VInfo.PValue = nil then Exit;
  fSetAsValue(value);
end;

function TAVValue.GetAsVariant: Variant;
begin
  if VInfo.PValue = nil then Exit(Unassigned);
  Result := fGetAsVariant;
end;

procedure TAVValue.SetAsVariant(value: Variant);
begin
  if VInfo.PValue = nil then Exit;
  fSetAsVariant(value);
end;

function TAVValue.GetAsBitArray: TBitArray;
begin
  if VInfo.PValue = nil then begin Result.ByteCount := 0; exit; end;
  Result := fGetAsBitArray;
end;

procedure TAVValue.SetAsBitArray(value: TBitArray);
begin
  if VInfo.PValue = nil then Exit;
  fSetAsBitArray(value);
end;

function TAVValue.GetAsType<T>: T;
begin
  if VInfo.PValue = nil then Exit(Default(T));

  if VInfo.ValueType = avtRecord then Result := RecordGetAsType<T>
  else
  case VInfo.ValueType of
    avtString: Result := StringGetAsType<T>;
    avtByte: Result := ByteGetAsType<T>;
    avtInt16: Result := Int16GetAsType<T>;
    avtInt32: Result := Int32GetAsType<T>;
    avtInt64: Result := Int64GetAsType<T>;
    avtNativeInt: Result := NativeIntGetAsType<T>;
    avtDouble: Result := FloatGetAsType<T>;
    avtObject: Result := ObjectGetAsType<T>;
    avtDate: Result := DateGetAsType<T>;
    avtBool: Result := BoolGetAsType<T>;
    avtValue: Result := ValueGetAsType<T>;
    avtVariant: Result := VariantGetAsType<T>;
    avtBitArray: Result := BitArrayGetAsType<T>;
  end;
end;

procedure TAVValue.SetAsType<T>(value: T);
begin
  if VInfo.PValue = nil then Exit;

  if VInfo.ValueType = avtRecord then RecordSetAsType<T>(value)
  else
  case VInfo.ValueType of
    avtString: StringSetAsType<T>(value);
    avtByte: ByteSetAsType<T>(value);
    avtInt16: Int16SetAsType<T>(value);
    avtInt32: Int32SetAsType<T>(value);
    avtInt64: Int64SetAsType<T>(value);
    avtNativeInt: NativeIntSetAsType<T>(value);
    avtDouble: FloatSetAsType<T>(value);
    avtObject: ObjectSetAsType<T>(value);
    avtDate: DateSetAsType<T>(value);
    avtBool: BoolSetAsType<T>(value);
    avtValue: ValueSetAsType<T>(value);
    avtVariant: VariantSetAsType<T>(value);
    avtBitArray: BitArraySetAsType<T>(value);
  end;
end;

function TAVValue.GetAsRtti: TAVRttiObj;
begin
  Result.Instance := VInfo.PValue;
  Result.TypeInfo := VInfo.ValueInfo;
end;

function TAVValue.GetFormatedValue(FormatStr: string): string;
begin
  if VInfo.PValue = nil then Exit('');
  Result := fGetFormatedValue(FormatStr);
end;

procedure TAVValue.SetFormatedValue(FormatStr: string; value: string);
begin
  if VInfo.PValue = nil then Exit;
  fSetFormatedValue(FormatStr, value);
end;

function TAVValue.IsEmpty: boolean;
begin
  if VInfo.PValue = nil then Exit(True);
  Result := fIsEmpty;
end;

function TAVValue.CompareTo(value: TAVValue): integer;
begin
  if VInfo.PValue = nil then Exit(0);
  Result := fCompareTo(value);
end;

procedure TAVValue.PointTo<T>(pvalue: Pointer);
var typeInfo: PTypeInfo;
begin
  typeInfo := System.TypeInfo(T);
  VInfo.PValue := pvalue;
  VInfo.ValueInfo := typeInfo;
  VInfo.ValueType := AVTypeFromTypeInfo(typeInfo);
  InitMethods;
end;

procedure TAVValue.PointTo<T>(var value: T);
begin
  PointTo<T>(@value);
end;

procedure TAVValue.PointToNewValue(pv: Pointer);
begin
  VInfo.PValue := pv;
end;

procedure TAVValue.CopyFrom(value: TAVValue);
begin
  if VInfo.PValue = nil then Exit;
  fCopyFrom(value);
end;

procedure TAVValue.InitMethods;
begin
  case VInfo.ValueType of
    avtString: StringInitMethods;
    avtByte: ByteInitMethods;
    avtInt16: Int16InitMethods;
    avtInt32: Int32InitMethods;
    avtInt64: Int64InitMethods;
    avtNativeInt: NativeIntInitMethods;
    avtDouble: FloatInitMethods;
    avtObject: ObjectInitMethods;
    avtDate: DateInitMethods;
    avtBool: BoolInitMethods;
    avtValue: ValueInitMethods;
    avtVariant: VariantInitMethods;
    avtBitArray: BitArrayInitMethods;
    avtRecord: RecordInitMethods;
  end;
end;

initialization

finalization

if fContextCreated then
begin
  fContext.Free;
  fContextCreated := false;
end;

end.
